Merge "provide wifi info from wifi_files.c"
diff --git a/cmds/wifi_files.c b/cmds/wifi_files.c
index 30eb952..7e5e82a 100644
--- a/cmds/wifi_files.c
+++ b/cmds/wifi_files.c
@@ -24,6 +24,7 @@
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
+#include <linux/if_ether.h>
#include <linux/nl80211.h>
#include <math.h>
#include <net/if.h>
@@ -46,6 +47,7 @@
#define STATIONS_DIR "/tmp/stations"
+#define WIFISHOW_DIR "/tmp/wifi/wifiinfo"
typedef struct client_state {
@@ -59,6 +61,7 @@
const char *interfaces[NINTERFACES];
int ninterfaces = 0;
+static FILE *wifi_show_handle = NULL;
int GetIfIndex(const char *ifname)
{
@@ -110,12 +113,16 @@
}
-void RequestInterfaceList(struct nl_sock *nlsk, int nl80211_id)
+void HandleNLCommand(struct nl_sock *nlsk, int nl80211_id, int n,
+ int cb(struct nl_msg *, void *),
+ int cmd, int flag)
{
struct nl_msg *msg;
+ int ifindex = n >= 0 ? ifindexes[n] : -1;
+ const char *ifname = n>=0 ? interfaces[n] : NULL;
if (nl_socket_modify_cb(nlsk, NL_CB_VALID, NL_CB_CUSTOM,
- InterfaceListCallback, NULL)) {
+ cb, (void *)ifname)) {
fprintf(stderr, "nl_socket_modify_cb failed\n");
exit(1);
}
@@ -124,18 +131,29 @@
fprintf(stderr, "nlmsg_alloc failed\n");
exit(1);
}
- if (genlmsg_put(msg, 0, 0, nl80211_id, 0, NLM_F_DUMP,
- NL80211_CMD_GET_INTERFACE, 0) == NULL) {
+ if (genlmsg_put(msg, 0, 0, nl80211_id, 0, flag,
+ cmd, 0) == NULL) {
fprintf(stderr, "genlmsg_put failed\n");
exit(1);
}
+ if (ifindex >= 0 && nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex)) {
+ fprintf(stderr, "NL80211_CMD_GET_STATION put IFINDEX failed\n");
+ exit(1);
+ }
+
if (nl_send_auto(nlsk, msg) < 0) {
fprintf(stderr, "nl_send_auto failed\n");
exit(1);
}
-
nlmsg_free(msg);
+}
+
+
+void RequestInterfaceList(struct nl_sock *nlsk, int nl80211_id)
+{
+ HandleNLCommand(nlsk, nl80211_id, -1, InterfaceListCallback,
+ NL80211_CMD_GET_INTERFACE, NLM_F_DUMP);
} /* RequestInterfaceList */
@@ -354,39 +372,10 @@
void RequestAssociatedDevices(struct nl_sock *nlsk, int nl80211_id, int n)
{
- struct nl_msg *msg;
- int ifindex = ifindexes[n];
- const char *ifname = interfaces[n];
-
- if (nl_socket_modify_cb(nlsk, NL_CB_VALID, NL_CB_CUSTOM,
- StationDumpCallback, (void *)ifname)) {
- fprintf(stderr, "nl_socket_modify_cb failed\n");
- exit(1);
- }
-
- if ((msg = nlmsg_alloc()) == NULL) {
- fprintf(stderr, "nlmsg_alloc failed\n");
- exit(1);
- }
- if (genlmsg_put(msg, 0, 0, nl80211_id, 0, NLM_F_DUMP,
- NL80211_CMD_GET_STATION, 0) == NULL) {
- fprintf(stderr, "genlmsg_put failed\n");
- exit(1);
- }
- if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex)) {
- fprintf(stderr, "NL80211_CMD_GET_STATION put IFINDEX failed\n");
- exit(1);
- }
-
- if (nl_send_auto(nlsk, msg) < 0) {
- fprintf(stderr, "nl_send_auto failed\n");
- exit(1);
- }
- nlmsg_free(msg);
+ HandleNLCommand(nlsk, nl80211_id, n, StationDumpCallback,
+ NL80211_CMD_GET_STATION, NLM_F_DUMP);
} /* RequestAssociatedDevices */
-
-
static int NlFinish(struct nl_msg *msg, void *arg)
{
int *ret = arg;
@@ -470,6 +459,166 @@
} /* usage */
+/* From iw package, try untouched except indentation */
+int ieee80211_frequency_to_channel(int freq)
+{
+ /* see 802.11-2007 17.3.8.3.2 and Annex J */
+ if (freq == 2484)
+ return 14;
+ else if (freq < 2484)
+ return (freq - 2407) / 5;
+ else if (freq >= 4910 && freq <= 4980)
+ return (freq - 4000) / 5;
+ else if (freq <= 45000) /* DMG band lower limit */
+ return (freq - 5000) / 5;
+ else if (freq >= 58320 && freq <= 64800)
+ return (freq - 56160) / 2160;
+ else
+ return 0;
+}
+
+
+void print_ssid_escaped(FILE* f, const uint8_t len, const uint8_t *data)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (isprint(data[i]) && data[i] != ' ' && data[i] != '\\')
+ fprintf(f, "%c", data[i]);
+ else if (data[i] == ' ' && (i != 0 && i != len -1))
+ fprintf(f," ");
+ else
+ fprintf(f, "\\x%.2x", data[i]);
+ }
+}
+
+
+static int WlanInfoCallback(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
+
+ nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (tb_msg[NL80211_ATTR_MAC]) {
+ unsigned char *mac_addr = nla_data(tb_msg[NL80211_ATTR_MAC]);
+ fprintf(wifi_show_handle,
+ " \"BSSID\": \"%02x:%02x:%02x:%02x:%02x:%02x\",\n",
+ mac_addr[0], mac_addr[1], mac_addr[2],
+ mac_addr[3], mac_addr[4], mac_addr[5]);
+ }
+ if (tb_msg[NL80211_ATTR_SSID]) {
+ fprintf(wifi_show_handle, " \"SSID\": \"");
+ print_ssid_escaped(wifi_show_handle, nla_len(tb_msg[NL80211_ATTR_SSID]),
+ nla_data(tb_msg[NL80211_ATTR_SSID]));
+ fprintf(wifi_show_handle, "\",\n");
+ }
+ if (tb_msg[NL80211_ATTR_WIPHY_FREQ]) {
+ uint32_t freq = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]);
+
+ fprintf(wifi_show_handle, " \"Channel\": %d",
+ ieee80211_frequency_to_channel(freq));
+
+ fprintf(wifi_show_handle, ",\n");
+ }
+
+ return NL_SKIP;
+}
+
+
+void UpdateWifiShowContent(struct nl_sock *nlsk, int nl80211_id, int n)
+{
+ HandleNLCommand(nlsk, nl80211_id, n, WlanInfoCallback,
+ NL80211_CMD_GET_INTERFACE, 0);
+}
+
+
+static int RegdomainCallback(struct nl_msg *msg, void *arg)
+{
+ struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ char *alpha2;
+
+ nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (!tb_msg[NL80211_ATTR_REG_ALPHA2]) {
+ return NL_SKIP;
+ }
+
+ if (!tb_msg[NL80211_ATTR_REG_RULES]) {
+ return NL_SKIP;
+ }
+
+ alpha2 = nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]);
+ fprintf(wifi_show_handle, " \"RegDomain\": \"%c%c\",\n", alpha2[0], alpha2[1]);
+
+ return NL_SKIP;
+}
+
+
+void UpdateWifiRegdomain(struct nl_sock *nlsk, int nl80211_id)
+{
+ HandleNLCommand(nlsk, nl80211_id, -1, RegdomainCallback,
+ NL80211_CMD_GET_REG, 0);
+}
+
+
+void UpdateWifiShow(struct nl_sock *nlsk, int nl80211_id, int n)
+{
+ char tmpfile[PATH_MAX];
+ char filename[PATH_MAX];
+ char autofile[PATH_MAX];
+ const char *ifname = interfaces[n];
+ int done = 0;
+ struct stat buffer;
+ FILE *fptr;
+
+ if (!ifname || !ifname[0]) {
+ return;
+ }
+
+ snprintf(tmpfile, sizeof(tmpfile), "%s/%s.new", WIFISHOW_DIR, ifname);
+ snprintf(filename, sizeof(filename), "%s/%s", WIFISHOW_DIR, ifname);
+
+ if ((wifi_show_handle = fopen(tmpfile, "w+")) == NULL) {
+ perror("fopen");
+ return;
+ }
+
+ fprintf(wifi_show_handle, "{\n");
+ done = 0;
+ UpdateWifiShowContent(nlsk, nl80211_id, n);
+ ProcessNetlinkMessages(nlsk, &done);
+
+ done = 0;
+ UpdateWifiRegdomain(nlsk, nl80211_id);
+ ProcessNetlinkMessages(nlsk, &done);
+
+ snprintf(autofile, sizeof(autofile), "/tmp/autochan.%s", ifname);
+ if (stat(autofile, &buffer) == 0) {
+ fprintf(wifi_show_handle, " \"AutoChannel\": true,\n");
+ } else {
+ fprintf(wifi_show_handle, " \"AutoChannel\": false,\n");
+ }
+ snprintf(autofile, sizeof(autofile), "/tmp/autotype.%s", ifname);
+ if ((fptr = fopen(autofile, "r")) == NULL) {
+ fprintf(wifi_show_handle, " \"AutoType\": \"LOW\"\n");
+ } else {
+ char buf[24];
+ fgets(buf, sizeof(buf), fptr);
+ fprintf(wifi_show_handle, " \"AutoType\": \"%s\"\n", buf);
+ }
+ fprintf(wifi_show_handle, "}\n");
+
+ fclose(wifi_show_handle);
+ wifi_show_handle = NULL;
+ if (rename(tmpfile, filename)) {
+ perror("rename");
+ }
+}
+
int main(int argc, char **argv)
{
int done = 0;
@@ -508,6 +657,8 @@
done = 0;
RequestAssociatedDevices(nlsk, nl80211_id, i);
ProcessNetlinkMessages(nlsk, &done);
+
+ UpdateWifiShow(nlsk, nl80211_id, i);
}
TouchUpdateFile();
sleep(2);