]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
add wiphy dump capability
authorJohannes Berg <johannes@sipsolutions.net>
Tue, 15 Jan 2008 23:21:59 +0000 (00:21 +0100)
committerJohannes Berg <johannes@sipsolutions.net>
Tue, 15 Jan 2008 23:21:59 +0000 (00:21 +0100)
Makefile
info.c [new file with mode: 0644]
iw.c
iw.h

index f4e2186c782a0bb16bec8d3c2b2b4c39d45e1662..5e620a521433c7dfd50b69d81e7413f8f1e2d549 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ CC ?= "gcc"
 CFLAGS += -Wall -I/lib/modules/`uname -r`/build/include -g
 LDFLAGS += -lnl
 
-OBJS = iw.o interface.o
+OBJS = iw.o interface.o info.o
 ALL = iw
 
 all: verify_config $(ALL)
diff --git a/info.c b/info.c
new file mode 100644 (file)
index 0000000..78b90ad
--- /dev/null
+++ b/info.c
@@ -0,0 +1,163 @@
+#include <errno.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+#include <linux/nl80211.h>
+
+#include <net/if.h>
+
+#include "iw.h"
+
+static void print_flag(const char *name, int *open)
+{
+       if (!*open)
+               printf(" (");
+       else
+               printf(", ");
+       printf(name);
+       *open = 1;
+}
+
+static int print_phy_handler(struct nl_msg *msg, void *arg)
+{
+       struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+
+       struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
+
+       struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
+       static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
+               [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
+               [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
+               [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
+               [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
+               [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
+       };
+
+       struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1];
+       static struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = {
+               [NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 },
+               [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] = { .type = NLA_FLAG },
+       };
+
+       struct nlattr *nl_band;
+       struct nlattr *nl_freq;
+       struct nlattr *nl_rate;
+       int bandidx = 1;
+       int rem_band, rem_freq, rem_rate;
+       int open;
+
+       nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+                 genlmsg_attrlen(gnlh, 0), NULL);
+
+       if (!tb_msg[NL80211_ATTR_WIPHY_BANDS])
+               return NL_SKIP;
+
+       nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) {
+               printf("Band %d:\n", bandidx);
+               bandidx++;
+
+               nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
+                         nla_len(nl_band), NULL);
+
+               printf("\tFrequencies:\n");
+
+               nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {
+                       nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),
+                                 nla_len(nl_freq), freq_policy);
+                       if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
+                               continue;
+                       printf("\t\t* %d MHz", nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]));
+                       open = 0;
+                       if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
+                               print_flag("disabled", &open);
+                       if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN])
+                               print_flag("passive scanning", &open);
+                       if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS])
+                               print_flag("no IBSS", &open);
+                       if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR])
+                               print_flag("radar detection", &open);
+                       if (open)
+                               printf(")");
+                       printf("\n");
+               }
+
+               printf("\tBitrates:\n");
+
+               nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) {
+                       nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate),
+                                 nla_len(nl_rate), rate_policy);
+                       if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
+                               continue;
+                       printf("\t\t* %2.1f Mbps", 0.1 * nla_get_u32(tb_rate[NL80211_BITRATE_ATTR_RATE]));
+                       open = 0;
+                       if (tb_rate[NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE])
+                               print_flag("short preamble supported", &open);
+                       if (open)
+                               printf(")");
+                       printf("\n");
+               }
+       }
+
+       return NL_SKIP;
+}
+
+
+
+static int ack_wait_handler(struct nl_msg *msg, void *arg)
+{
+       int *finished = arg;
+
+       *finished = 1;
+       return NL_STOP;
+}
+
+int handle_info(struct nl80211_state *state, char *phy, char *dev)
+{
+       struct nl_msg *msg;
+       int err = -1;
+       struct nl_cb *cb = NULL;
+       int finished;
+
+       msg = nlmsg_alloc();
+       if (!msg) {
+               fprintf(stderr, "failed to allocate netlink msg\n");
+               return -1;
+       }
+
+       genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
+                   0, NL80211_CMD_GET_WIPHY, 0);
+       if (dev)
+               NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(dev));
+       if (phy)
+               return -1;      /* XXX TODO */
+
+       cb = nl_cb_alloc(NL_CB_CUSTOM);
+       if (!cb)
+               goto out;
+
+       if (nl_send_auto_complete(state->nl_handle, msg) < 0)
+               goto out;
+
+       nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_phy_handler, NULL);
+       nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, &finished);
+
+       err = nl_recvmsgs(state->nl_handle, cb);
+
+       if (!finished)
+               err = nl_wait_for_ack(state->nl_handle);
+
+       if (err < 0)
+               goto out;
+       err = 0;
+
+ out:
+       nl_cb_put(cb);
+ nla_put_failure:
+       if (err)
+               fprintf(stderr, "failed to get information: %d\n", err);
+       nlmsg_free(msg);
+       return err;
+}
diff --git a/iw.c b/iw.c
index 469bf0e064e612bdf2aa161db35174dd043e8161..a51229f3536ea7480a532c21aeedc69334c5bf5b 100644 (file)
--- a/iw.c
+++ b/iw.c
@@ -92,7 +92,9 @@ static int get_phy_or_dev(int *argc, char ***argv, char **name)
 
 void usage(char *argv0)
 {
-       fprintf(stderr, "Usage: %s dev <phydev> interface <COMMAND> [OPTIONS]\n"
+       fprintf(stderr, "Usage: %1$s dev <phydev> interface <COMMAND> [OPTIONS]\n"
+                       "       %1$s dev <phydev> info\n"
+                       "\n"
                        "where COMMAND := { add | del }\n"
                        "\n"
                        "For add, OPTIONS := <name> type <type>\n"
@@ -140,6 +142,8 @@ int main(int argc, char **argv)
 
        if (strcmp(type, "interface") == 0)
                err = handle_interface(&nlstate, phyname, ifname, argc, argv);
+       if (strcmp(type, "info") == 0)
+               err = handle_info(&nlstate, phyname, ifname);
        else {
                fprintf(stderr, "No such object type %s\n", type);
                err = 1;
diff --git a/iw.h b/iw.h
index a4db8f70932b3c0dd8a58ef032afe3eadc184165..3fad652bedc0ff08083f2a5c0ce2665573fbc668 100644 (file)
--- a/iw.h
+++ b/iw.h
@@ -15,4 +15,6 @@ struct nl80211_state {
 int handle_interface(struct nl80211_state *state,
                     char *phy, char *dev, int argc, char **argv);
 
+int handle_info(struct nl80211_state *state, char *phy, char *dev);
+
 #endif /* __IW_H */