Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gluon independent respondd-wifi package #217

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions net/respondd-wifi/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
include $(TOPDIR)/rules.mk

PKG_NAME:=respondd-wifi
PKG_VERSION:=1
PKG_RELEASE:=1

PKG_LICENSE:=BSD-2-Clause

PKG_BUILD_DEPENDS := respondd

include $(INCLUDE_DIR)/package.mk

TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include/libnl-tiny

define Package/respondd-wifi/Default
SECTION:=net
CATEGORY:=Network
TITLE:=Add wifi statistics to respondd
DEPENDS:=+respondd +libnl-tiny
endef

define Package/respondd-wifi/install
$(INSTALL_DIR) $(1)/usr/lib/respondd
$(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/usr/lib/respondd/wifi.so
endef

$(eval $(call BuildPackage,respondd-wifi))
26 changes: 26 additions & 0 deletions net/respondd-wifi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
This module adds a respondd wifi usage statistics provider.
The format is the following:

```json
{
"statistics": {
"clients":{
"wifi24": 3,
"wifi5": 7
},
},
"neighbours": {
"wifi":{
"00:11:22:33:44:55:66":{
"frequency": 5220,
"neighbours":{
"33:22:33:11:22:44":{
"signal": 191,
"inactive": 50
}
}
}
}
}
}
```
16 changes: 16 additions & 0 deletions net/respondd-wifi/src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# standard compliance
CFLAGS += -std=c99

# warnings
CFLAGS += -Wall -Wextra -Wformat=2 -Wshadow -Wpointer-arith
CFLAGS += -pedantic

all: respondd.so

%.c: %.h

respondd.so: netlink.c ifaces.c airtime.c clients.c neighbours.c respondd.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -lnl-tiny -o $@ $^ $(LDLIBS)

clean:
rm -rf *.so
16 changes: 16 additions & 0 deletions net/respondd-wifi/src/clients.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <linux/nl80211.h>
#include <netlink/genl/genl.h>

#include "netlink.h"
#include "clients.h"

static int station_client_handler(struct nl_msg *msg, void *arg) {
int *count = (int *) arg;

(*count)++;

return NL_SKIP;
}
bool get_client_counts(int *count, int ifx) {
return nl_send_dump(station_client_handler, count, NL80211_CMD_GET_STATION, ifx);
}
5 changes: 5 additions & 0 deletions net/respondd-wifi/src/clients.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include <stdbool.h>

__attribute__((visibility("hidden"))) bool get_client_counts(int *count, int ifx);
41 changes: 41 additions & 0 deletions net/respondd-wifi/src/ifaces.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <linux/nl80211.h>
#include <netlink/genl/genl.h>

#include "ifaces.h"
#include "netlink.h"


static int iface_dump_handler(struct nl_msg *msg, void *arg) {
struct nlattr *tb[NL80211_ATTR_MAX + 1];
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct iface_list **last_next;

nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);

if (!tb[NL80211_ATTR_WIPHY] || !tb[NL80211_ATTR_IFINDEX])
goto skip;

// TODO fix add to head list - instatt find last item
for (last_next = arg; *last_next != NULL; last_next = &(*last_next)->next) {}

*last_next = malloc(sizeof(**last_next));
if (!*last_next)
goto skip;
(*last_next)->next = NULL;
(*last_next)->ifx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
(*last_next)->frequency = tb[NL80211_ATTR_WIPHY_FREQ] ? nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]) : 0;
(*last_next)->type = tb[NL80211_ATTR_IFTYPE] ? nla_get_u32(tb[NL80211_ATTR_IFTYPE]) : 0;

if(tb[NL80211_ATTR_MAC]) {
mac_addr_n2a((*last_next)->mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
}

skip:
return NL_SKIP;
}

struct iface_list *get_ifaces() {
struct iface_list *ifaces = NULL;
nl_send_dump(&iface_dump_handler, &ifaces, NL80211_CMD_GET_INTERFACE, 0);
return ifaces;
}
13 changes: 13 additions & 0 deletions net/respondd-wifi/src/ifaces.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include <stdbool.h>

struct iface_list {
int ifx;
char mac_addr[20];
int type;
int frequency;
struct iface_list *next;
};

__attribute__((visibility("hidden"))) struct iface_list *get_ifaces();
86 changes: 86 additions & 0 deletions net/respondd-wifi/src/neighbours.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include <linux/nl80211.h>
#include <netlink/genl/genl.h>

#include "netlink.h"
#include "neighbours.h"

static const char * neighbours_names[NL80211_STA_INFO_MAX + 1] = {
[NL80211_STA_INFO_SIGNAL] = "signal",
[NL80211_STA_INFO_INACTIVE_TIME] = "inactive",
};

static int station_neighbours_handler(struct nl_msg *msg, void *arg) {
struct json_object *neighbour, *json = (struct json_object *) arg;

neighbour = json_object_new_object();
if (!neighbour)
goto abort;

struct nlattr *tb[NL80211_ATTR_MAX + 1];

struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct nlattr *station_info = nla_find(genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NL80211_ATTR_STA_INFO);

nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);

if (!station_info) {
fputs("respondd-wifi: station data missing in netlink message\n", stderr);
json_object_put(neighbour);
goto abort;
}

char mac_addr[20];

if (!tb[NL80211_ATTR_MAC]) {
json_object_put(neighbour);
goto abort;
}
mac_addr_n2a(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));

int rem;
struct nlattr *nla;
nla_for_each_nested(nla, station_info, rem) {
int type = nla_type(nla);

if (type > NL80211_STA_INFO_MAX)
continue;

if (!neighbours_names[type])
continue;

struct json_object *data_json = NULL;
switch (nla_len(nla)) {
case sizeof(uint64_t):
data_json = json_object_new_int64(nla_get_u64(nla));
break;
case sizeof(uint32_t):
data_json = json_object_new_int(nla_get_u32(nla));
break;
case sizeof(uint8_t):
data_json = json_object_new_int(nla_get_u8(nla));
break;
default:
fprintf(stderr, "respondd-wifi: Unexpected NL attribute length: %d\n", nla_len(nla));
}
if (data_json)
json_object_object_add(neighbour, neighbours_names[type], data_json);
}
json_object_object_add(json, mac_addr, neighbour);

abort:
return NL_SKIP;
}

bool get_neighbours(struct json_object *result, int ifx) {
struct json_object *neighbours;
neighbours = json_object_new_object();
if (!neighbours)
return false;
if(!nl_send_dump(station_neighbours_handler, neighbours, NL80211_CMD_GET_STATION, ifx)) {
json_object_put(neighbours);
return false;
}
json_object_object_add(result, "neighbours", neighbours);
return true;

}
6 changes: 6 additions & 0 deletions net/respondd-wifi/src/neighbours.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#pragma once

#include <stdbool.h>
#include <json-c/json.h>

__attribute__((visibility("hidden"))) bool get_neighbours(struct json_object *result, int ifx);
73 changes: 73 additions & 0 deletions net/respondd-wifi/src/netlink.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <inttypes.h>

#include <linux/nl80211.h>
#include <linux/if_ether.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>

#include "netlink.h"


void mac_addr_n2a(char *mac_addr, unsigned char *arg) {
sprintf(mac_addr, "%02x:%02x:%02x:%02x:%02x:%02x", arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
}


bool nl_send_dump(nl_recvmsg_msg_cb_t cb, void *cb_arg, int cmd, uint32_t cmd_arg) {
bool ok = false;
int ret;
int ctrl;
struct nl_sock *sk = NULL;
struct nl_msg *msg = NULL;


#define ERR(...) { fprintf(stderr, "respondd-wifi: " __VA_ARGS__); goto out; }

sk = nl_socket_alloc();
if (!sk)
ERR("nl_socket_alloc() failed\n");

ret = genl_connect(sk);
if (ret < 0)
ERR("genl_connect() returned %d\n", ret);

ctrl = genl_ctrl_resolve(sk, NL80211_GENL_NAME);
if (ctrl < 0)
ERR("genl_ctrl_resolve() returned %d\n", ctrl);

ret = nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, cb, cb_arg);
if (ret != 0)
ERR("nl_socket_modify_cb() returned %d\n", ret);

msg = nlmsg_alloc();
if (!msg)
ERR("nlmsg_alloc() failed\n");

if (!genlmsg_put(msg, 0, 0, ctrl, 0, NLM_F_DUMP, cmd, 0))
ERR("genlmsg_put() failed while putting cmd %d\n", ret, cmd);

if (cmd_arg != 0)
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, cmd_arg);

ret = nl_send_auto_complete(sk, msg);
if (ret < 0)
ERR("nl_send_auto() returned %d while sending cmd %d with cmd_arg=%"PRIu32"\n", ret, cmd, cmd_arg);

ret = nl_recvmsgs_default(sk);
if (ret < 0)
ERR("nl_recv_msgs_default() returned %d while receiving cmd %d with cmd_arg=%"PRIu32"\n", ret, cmd, cmd_arg);

#undef ERR

ok = true;

nla_put_failure:
out:
if (msg)
nlmsg_free(msg);

if (sk)
nl_socket_free(sk);

return ok;
}
8 changes: 8 additions & 0 deletions net/respondd-wifi/src/netlink.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

#include <stdbool.h>
#include <stdint.h>
#include <netlink/handlers.h>

__attribute__((visibility("hidden"))) void mac_addr_n2a(char *mac_addr, unsigned char *arg);
__attribute__((visibility("hidden"))) bool nl_send_dump(nl_recvmsg_msg_cb_t cb, void *cb_arg, int cmd, uint32_t cmd_arg);
Loading