From: Matthias Schiffer <mschiffer@universe-factory.net>
To: b.a.t.m.a.n@lists.open-mesh.org
Subject: Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
Date: Thu, 17 Mar 2016 18:04:56 +0100 [thread overview]
Message-ID: <56EAE3B8.3050808@universe-factory.net> (raw)
In-Reply-To: <cover.1458231707.git.mschiffer@universe-factory.net>
[-- Attachment #1.1.1: Type: text/plain, Size: 1947 bytes --]
On 03/17/2016 05:45 PM, Matthias Schiffer wrote:
> Hi,
> this is the second take of my netlink API patches. As mentioned before, the
> netlink API is superior to the current debugfs API in many aspects:
>
> * debugfs is broken (see PATCH 1 for details)
> * Netlink is namespace-aware, and can be used in unprivileged containers
> without problems
> * Netlink packets are more machine-readable than text files, and can be
> easily extended without potentially breaking userspace
> * On older kernels, seq_file can't fall back to vmalloc if kmalloc fails,
> which often leads to OOM when reading "originators" in large meshes, as
> the whole file must fit into a single buffer
>
> Of course, are also a few downsides; when the data is too big to fit into
> a single netlink packet, the provided data may be inconsistent (entries may
> be missing or duplicated.) This will happen in large meshes only, and be
> improbable in any case.
>
> The patches have been developed on top of the netns patchset, but should
> be applicable independently (maybe with minor changes.)
>
> All netlink queries returning lists of any kind can only be used with
> NLM_F_DUMP queries, so that arbitrarity large responses are possible (split
> across multiple packets if necessary.)
>
> At the moment, the following debugfs files have corresponding netlink APIs:
>
> * routing_algos
> * neighbors
> * originators
> * transtable_global
> * transtable_local
> * (hardinterfaces for a softif can be queried)
>
> The following files are still missing:
>
> * gateways
> * bla_claim_table
> * bla_backbone_table
> * dat_cache
> * nc_nodes
>
> Obviously, documentation is also a TODO. Comments about the API design are
> very welcome...
>
> Regards,
> Matthias
>
>
And here is the new version of the PoC userspace tool.
Build with:
gcc -o batnl batnl.c $$(pkg-config --cflags --libs libnl-1) -Wall
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.1.2: batnl.c --]
[-- Type: text/x-csrc; name="batnl.c", Size: 16521 bytes --]
#include <stdio.h>
#include <string.h>
#include <net/if.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "batman_adv.h"
static void usage()
{
fprintf(stderr, "Usage:\n\n");
fprintf(stderr, " batnl routing_algos\n");
fprintf(stderr, " batnl info <mesh>\n");
fprintf(stderr, " batnl interface <mesh>\n");
fprintf(stderr, " batnl translocal <mesh>\n");
fprintf(stderr, " batnl transglobal <mesh>\n");
fprintf(stderr, " batnl neighbors <mesh> [<hardif>]\n");
fprintf(stderr, " batnl originators <mesh> [<hardif>]\n");
exit(2);
}
static int print_error(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg)
{
fprintf(stderr, "Error received: %s\n", strerror(-nlerr->error));
exit(1);
}
static int stop_callback(struct nl_msg *msg, void *arg)
{
struct nlmsghdr *nlh = nlmsg_hdr(msg);
int *error = nlmsg_data(nlh);
if (*error)
fprintf(stderr, "Error received: %s\n", strerror(-*error));
return NL_STOP;
}
static int routing_algos_callback(struct nl_msg *msg, void *arg)
{
struct nlmsghdr *nlh = nlmsg_hdr(msg);
struct genlmsghdr *ghdr;
struct nlattr *attrs[BATADV_ATTR_MAX+1];
if (!genlmsg_valid_hdr(nlh, 0)) {
fputs("Received invalid data from kernel.", stderr);
exit(1);
}
ghdr = nlmsg_data(nlh);
if (ghdr->cmd != BATADV_CMD_GET_ROUTING_ALGOS)
return NL_OK;
if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), genlmsg_len(ghdr), NULL)) {
fputs("Received invalid data from kernel.", stderr);
exit(1);
}
const char *algo_name = nla_get_string(attrs[BATADV_ATTR_ALGO_NAME]);
printf(" * %s\n", algo_name);
return NL_OK;
}
static void routing_algos(struct nl_handle *sock, int family)
{
struct nl_msg *msg;
struct nl_cb *cb;
msg = nlmsg_alloc();
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_DUMP, BATADV_CMD_GET_ROUTING_ALGOS, 1);
nl_send_auto_complete(sock, msg);
nlmsg_free(msg);
cb = nl_cb_alloc(NL_CB_DEFAULT);
nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, routing_algos_callback, NULL);
nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);
nl_recvmsgs(sock, cb);
}
static int info_callback(struct nl_msg *msg, void *arg)
{
struct nlmsghdr *nlh = nlmsg_hdr(msg);
struct genlmsghdr *ghdr;
struct nlattr *attrs[BATADV_ATTR_MAX+1];
if (!genlmsg_valid_hdr(nlh, 0)) {
fputs("Received invalid data from kernel.", stderr);
exit(1);
}
ghdr = nlmsg_data(nlh);
if (ghdr->cmd != BATADV_CMD_GET_MESH_INFO)
return NL_OK;
if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), genlmsg_len(ghdr), NULL)) {
fputs("Received invalid data from kernel.", stderr);
exit(1);
}
const char *mesh_name = nla_get_string(attrs[BATADV_ATTR_MESH_IFNAME]);
if (attrs[BATADV_ATTR_HARD_IFNAME]) {
const char *version = nla_get_string(attrs[BATADV_ATTR_VERSION]);
const char *algo_name = nla_get_string(attrs[BATADV_ATTR_ALGO_NAME]);
const char *primary_if = nla_get_string(attrs[BATADV_ATTR_HARD_IFNAME]);
const uint8_t *primary_mac = nla_data(attrs[BATADV_ATTR_HARD_ADDRESS]);
printf("[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%02x:%02x:%02x:%02x:%02x:%02x (%s %s)]\n",
version, primary_if,
primary_mac[0], primary_mac[1], primary_mac[2],
primary_mac[3], primary_mac[4], primary_mac[5],
mesh_name, algo_name);
}
else {
printf("BATMAN mesh %s disabled\n", mesh_name);
}
return NL_STOP;
}
static void info(struct nl_handle *sock, int family, int ifindex)
{
struct nl_msg *msg;
struct nl_cb *cb;
msg = nlmsg_alloc();
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, 0, BATADV_CMD_GET_MESH_INFO, 1);
nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);
nl_send_auto_complete(sock, msg);
nlmsg_free(msg);
cb = nl_cb_alloc(NL_CB_DEFAULT);
nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, info_callback, NULL);
nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);
nl_recvmsgs(sock, cb);
}
static int interface_callback(struct nl_msg *msg, void *arg)
{
struct nlmsghdr *nlh = nlmsg_hdr(msg);
struct genlmsghdr *ghdr;
struct nlattr *attrs[BATADV_ATTR_MAX+1];
if (!genlmsg_valid_hdr(nlh, 0)) {
fputs("Received invalid data from kernel.", stderr);
exit(1);
}
ghdr = nlmsg_data(nlh);
if (ghdr->cmd != BATADV_CMD_GET_HARDIFS)
return NL_OK;
if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), genlmsg_len(ghdr), NULL)) {
fputs("Received invalid data from kernel.", stderr);
exit(1);
}
const char *ifname = nla_get_string(attrs[BATADV_ATTR_HARD_IFNAME]);
printf("%s: %sactive\n", ifname, attrs[BATADV_ATTR_ACTIVE] ? "" : "in");
return NL_OK;
}
static void interface(struct nl_handle *sock, int family, int ifindex)
{
struct nl_msg *msg;
struct nl_cb *cb;
msg = nlmsg_alloc();
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_DUMP, BATADV_CMD_GET_HARDIFS, 1);
nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);
nl_send_auto_complete(sock, msg);
nlmsg_free(msg);
cb = nl_cb_alloc(NL_CB_DEFAULT);
nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, interface_callback, NULL);
nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);
nl_recvmsgs(sock, cb);
}
static int translocal_callback(struct nl_msg *msg, void *arg)
{
struct nlmsghdr *nlh = nlmsg_hdr(msg);
struct genlmsghdr *ghdr;
struct nlattr *attrs[BATADV_ATTR_MAX+1];
if (!genlmsg_valid_hdr(nlh, 0)) {
fputs("Received invalid data from kernel.", stderr);
exit(1);
}
ghdr = nlmsg_data(nlh);
if (ghdr->cmd != BATADV_CMD_GET_TRANSTABLE_LOCAL)
return NL_OK;
if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), genlmsg_len(ghdr), NULL)) {
fputs("Received invalid data from kernel.", stderr);
exit(1);
}
uint8_t *addr = nla_data(attrs[BATADV_ATTR_TT_ADDRESS]);
int16_t vid = nla_get_u16(attrs[BATADV_ATTR_TT_VID]);
uint32_t crc32 = nla_get_u32(attrs[BATADV_ATTR_TT_CRC32]);
uint32_t flags = nla_get_u32(attrs[BATADV_ATTR_TT_FLAGS]);
int last_seen_msecs = 0, last_seen_secs = 0;
char r = '.', p = '.', n = '.', x = '.', w = '.', i = '.';
if (flags & BATADV_TT_CLIENT_ROAM)
r = 'R';
if (flags & BATADV_TT_CLIENT_NEW)
n = 'N';
if (flags & BATADV_TT_CLIENT_PENDING)
x = 'X';
if (flags & BATADV_TT_CLIENT_WIFI)
w = 'W';
if (flags & BATADV_TT_CLIENT_ISOLA)
i = 'I';
if (flags & BATADV_TT_CLIENT_NOPURGE) {
p = 'P';
}
else {
last_seen_msecs = nla_get_u32(attrs[BATADV_ATTR_LAST_SEEN_MSECS]);
last_seen_secs = last_seen_msecs / 1000;
last_seen_msecs = last_seen_msecs % 1000;
}
printf(" * %02x:%02x:%02x:%02x:%02x:%02x %4i [%c%c%c%c%c%c] %3u.%03u (0x%.8x)\n",
addr[0], addr[1], addr[2],
addr[3], addr[4], addr[5],
vid, r, p, n, x, w, i,
last_seen_secs, last_seen_msecs,
crc32);
return NL_OK;
}
static void translocal(struct nl_handle *sock, int family, int ifindex)
{
struct nl_msg *msg;
struct nl_cb *cb;
msg = nlmsg_alloc();
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_DUMP, BATADV_CMD_GET_TRANSTABLE_LOCAL, 1);
nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);
nl_send_auto_complete(sock, msg);
nlmsg_free(msg);
cb = nl_cb_alloc(NL_CB_DEFAULT);
nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, translocal_callback, NULL);
nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);
nl_recvmsgs(sock, cb);
}
static int transglobal_callback(struct nl_msg *msg, void *arg)
{
struct nlmsghdr *nlh = nlmsg_hdr(msg);
struct genlmsghdr *ghdr;
struct nlattr *attrs[BATADV_ATTR_MAX+1];
if (!genlmsg_valid_hdr(nlh, 0)) {
fputs("Received invalid data from kernel.", stderr);
exit(1);
}
ghdr = nlmsg_data(nlh);
if (ghdr->cmd != BATADV_CMD_GET_TRANSTABLE_GLOBAL)
return NL_OK;
if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), genlmsg_len(ghdr), NULL)) {
fputs("Received invalid data from kernel.", stderr);
exit(1);
}
uint8_t *addr = nla_data(attrs[BATADV_ATTR_TT_ADDRESS]);
uint8_t *orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
int16_t vid = nla_get_u16(attrs[BATADV_ATTR_TT_VID]);
uint8_t ttvn = nla_get_u8(attrs[BATADV_ATTR_TT_TTVN]);
uint8_t last_ttvn = nla_get_u8(attrs[BATADV_ATTR_TT_LAST_TTVN]);
uint32_t crc32 = nla_get_u32(attrs[BATADV_ATTR_TT_CRC32]);
uint32_t flags = nla_get_u32(attrs[BATADV_ATTR_TT_FLAGS]);
char c = '+', r = '.', w = '.', i = '.', t = '.';
if (attrs[BATADV_ATTR_FLAG_BEST])
c = '*';
if (flags & BATADV_TT_CLIENT_ROAM)
r = 'R';
if (flags & BATADV_TT_CLIENT_WIFI)
w = 'W';
if (flags & BATADV_TT_CLIENT_ISOLA)
i = 'I';
if (flags & BATADV_TT_CLIENT_TEMP)
t = 'T';
printf(" %c %02x:%02x:%02x:%02x:%02x:%02x %4i (%3u) via %02x:%02x:%02x:%02x:%02x:%02x (%3u) (0x%.8x) [%c%c%c%c]\n",
c,
addr[0], addr[1], addr[2],
addr[3], addr[4], addr[5],
vid, ttvn,
orig[0], orig[1], orig[2],
orig[3], orig[4], orig[5],
last_ttvn, crc32, r, w, i, t);
return NL_OK;
}
static void transglobal(struct nl_handle *sock, int family, int ifindex)
{
struct nl_msg *msg;
struct nl_cb *cb;
msg = nlmsg_alloc();
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_DUMP, BATADV_CMD_GET_TRANSTABLE_GLOBAL, 1);
nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);
nl_send_auto_complete(sock, msg);
nlmsg_free(msg);
cb = nl_cb_alloc(NL_CB_DEFAULT);
nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, transglobal_callback, NULL);
nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);
nl_recvmsgs(sock, cb);
}
static int originators_callback(struct nl_msg *msg, void *arg)
{
struct nlmsghdr *nlh = nlmsg_hdr(msg);
struct genlmsghdr *ghdr;
struct nlattr *attrs[BATADV_ATTR_MAX+1];
if (!genlmsg_valid_hdr(nlh, 0)) {
fputs("Received invalid data from kernel.", stderr);
exit(1);
}
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), NULL)) {
fputs("Received invalid data from kernel.", stderr);
exit(1);
}
uint8_t *orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
uint8_t *neigh = nla_data(attrs[BATADV_ATTR_NEIGH_ADDRESS]);
char ifname[IF_NAMESIZE];
if (!if_indextoname(nla_get_u32(attrs[BATADV_ATTR_HARD_IFINDEX]), ifname))
ifname[0] = '\0';
char c = '+';
if (attrs[BATADV_ATTR_FLAG_BEST])
c = '*';
int last_seen_msecs, last_seen_secs;
last_seen_msecs = nla_get_u32(attrs[BATADV_ATTR_LAST_SEEN_MSECS]);
last_seen_secs = last_seen_msecs / 1000;
last_seen_msecs = last_seen_msecs % 1000;
if (attrs[BATADV_ATTR_THROUGHPUT]) {
unsigned throughput_mbits, throughput_kbits;
throughput_kbits = nla_get_u32(attrs[BATADV_ATTR_THROUGHPUT]);
throughput_mbits = throughput_kbits / 1000;
throughput_kbits = throughput_kbits % 1000;
printf(" %c %02x:%02x:%02x:%02x:%02x:%02x %4i.%03is (%9u.%1u) %02x:%02x:%02x:%02x:%02x:%02x [%10s]\n",
c,
orig[0], orig[1], orig[2],
orig[3], orig[4], orig[5],
last_seen_secs, last_seen_msecs,
throughput_mbits, throughput_kbits / 100,
neigh[0], neigh[1], neigh[2],
neigh[3], neigh[4], neigh[5],
ifname);
}
else {
uint8_t tq = nla_get_u8(attrs[BATADV_ATTR_TQ]);
printf(" %c %02x:%02x:%02x:%02x:%02x:%02x %4i.%03is (%3i) %02x:%02x:%02x:%02x:%02x:%02x [%10s]\n",
c,
orig[0], orig[1], orig[2],
orig[3], orig[4], orig[5],
last_seen_secs, last_seen_msecs, tq,
neigh[0], neigh[1], neigh[2],
neigh[3], neigh[4], neigh[5],
ifname);
}
return NL_OK;
}
static void originators(struct nl_handle *sock, int family, int ifindex, int hard_ifindex)
{
struct nl_msg *msg;
struct nl_cb *cb;
msg = nlmsg_alloc();
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_DUMP, BATADV_CMD_GET_ORIGINATORS, 1);
nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);
if (hard_ifindex)
nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, hard_ifindex);
nl_send_auto_complete(sock, msg);
nlmsg_free(msg);
cb = nl_cb_alloc(NL_CB_DEFAULT);
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, originators_callback, NULL);
nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);
nl_recvmsgs(sock, cb);
}
static int neighbors_callback(struct nl_msg *msg, void *arg)
{
struct nlmsghdr *nlh = nlmsg_hdr(msg);
struct genlmsghdr *ghdr;
struct nlattr *attrs[BATADV_ATTR_MAX+1];
if (!genlmsg_valid_hdr(nlh, 0)) {
fputs("Received invalid data from kernel.", stderr);
exit(1);
}
ghdr = nlmsg_data(nlh);
if (ghdr->cmd != BATADV_CMD_GET_NEIGHBORS)
return NL_OK;
if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), genlmsg_len(ghdr), NULL)) {
fputs("Received invalid data from kernel.", stderr);
exit(1);
}
uint8_t *neigh = nla_data(attrs[BATADV_ATTR_NEIGH_ADDRESS]);
char ifname[IF_NAMESIZE];
if (!if_indextoname(nla_get_u32(attrs[BATADV_ATTR_HARD_IFINDEX]), ifname))
ifname[0] = '\0';
int last_seen_msecs, last_seen_secs;
last_seen_msecs = nla_get_u32(attrs[BATADV_ATTR_LAST_SEEN_MSECS]);
last_seen_secs = last_seen_msecs / 1000;
last_seen_msecs = last_seen_msecs % 1000;
if (attrs[BATADV_ATTR_THROUGHPUT]) {
unsigned throughput_mbits, throughput_kbits;
throughput_kbits = nla_get_u32(attrs[BATADV_ATTR_THROUGHPUT]);
throughput_mbits = throughput_kbits / 1000;
throughput_kbits = throughput_kbits % 1000;
printf("%02x:%02x:%02x:%02x:%02x:%02x %4i.%03is (%9u.%1u) [%10s]\n",
neigh[0], neigh[1], neigh[2],
neigh[3], neigh[4], neigh[5],
last_seen_secs, last_seen_msecs,
throughput_mbits, throughput_kbits / 100,
ifname);
}
else {
printf(" %10s %02x:%02x:%02x:%02x:%02x:%02x %4i.%03is\n",
ifname,
neigh[0], neigh[1], neigh[2],
neigh[3], neigh[4], neigh[5],
last_seen_secs, last_seen_msecs);
}
return NL_OK;
}
static void neighbors(struct nl_handle *sock, int family, int ifindex, int hard_ifindex)
{
struct nl_msg *msg;
struct nl_cb *cb;
msg = nlmsg_alloc();
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_DUMP, BATADV_CMD_GET_NEIGHBORS, 1);
nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);
if (hard_ifindex)
nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, hard_ifindex);
nl_send_auto_complete(sock, msg);
nlmsg_free(msg);
cb = nl_cb_alloc(NL_CB_DEFAULT);
nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, neighbors_callback, NULL);
nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);
nl_recvmsgs(sock, cb);
}
int main(int argc, char *argv[])
{
struct nl_handle *sock;
int family;
sock = nl_handle_alloc();
genl_connect(sock);
family = genl_ctrl_resolve(sock, BATADV_NL_NAME);
if (family < 0) {
fputs("Your kernel doesn't support the batman-adv netlink interface.\n", stderr);
exit(1);
}
if (argc < 2 || argc > 4)
usage();
int ifindex = 0;
if (argc > 2) {
ifindex = if_nametoindex(argv[2]);
if (!ifindex)
usage();
}
int hard_ifindex = 0;
if (argc > 3) {
hard_ifindex = if_nametoindex(argv[3]);
if (!hard_ifindex)
usage();
}
if (!strcmp(argv[1], "routing_algos"))
routing_algos(sock, family);
else if (!strcmp(argv[1], "info"))
info(sock, family, ifindex);
else if (!strcmp(argv[1], "interface"))
interface(sock, family, ifindex);
else if (!strcmp(argv[1], "translocal"))
translocal(sock, family, ifindex);
else if (!strcmp(argv[1], "transglobal"))
transglobal(sock, family, ifindex);
else if (!strcmp(argv[1], "originators"))
originators(sock, family, ifindex, hard_ifindex);
else if (!strcmp(argv[1], "neighbors"))
neighbors(sock, family, ifindex, hard_ifindex);
else
usage();
return 0;
}
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
next prev parent reply other threads:[~2016-03-17 17:04 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-03-17 16:45 [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Matthias Schiffer
2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 1/5] batman-adv: add generic netlink query API to replace debugfs files Matthias Schiffer
2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 2/5] batman-adv: netlink: add translation table query Matthias Schiffer
2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 3/5] batman-adv: netlink: add originator and neighbor table queries Matthias Schiffer
2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 4/5] batman-adv: add B.A.T.M.A.N. IV bat_{orig, neigh}_dump implementations Matthias Schiffer
2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 5/5] batman-adv: add B.A.T.M.A.N. V " Matthias Schiffer
2016-03-17 17:04 ` Matthias Schiffer [this message]
2016-03-18 7:09 ` [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Sven Eckelmann
2016-03-18 11:53 ` Matthias Schiffer
2016-04-18 10:59 ` Sven Eckelmann
2016-03-18 11:23 ` Sven Eckelmann
2016-03-18 12:00 ` Matthias Schiffer
2016-03-18 12:04 ` Sven Eckelmann
2016-03-19 8:49 ` Antonio Quartulli
2016-03-19 9:19 ` Sven Eckelmann
2016-04-18 11:10 ` Sven Eckelmann
2016-04-18 14:50 ` Simon Wunderlich
2016-04-20 2:31 ` Andrew Lunn
2016-04-20 11:39 ` Simon Wunderlich
2016-04-20 7:32 ` Matthias Schiffer
2016-04-20 7:39 ` Sven Eckelmann
2016-04-20 7:49 ` Matthias Schiffer
2016-04-20 7:53 ` Sven Eckelmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=56EAE3B8.3050808@universe-factory.net \
--to=mschiffer@universe-factory.net \
--cc=b.a.t.m.a.n@lists.open-mesh.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox