]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
iw: add regulatory events notification parsing
authorLuis R. Rodriguez <lrodriguez@atheros.com>
Tue, 10 Mar 2009 02:28:50 +0000 (22:28 -0400)
committerJohannes Berg <johannes@sipsolutions.net>
Wed, 11 Mar 2009 13:45:55 +0000 (14:45 +0100)
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
iw.c
iw.h
reg.c

diff --git a/iw.c b/iw.c
index 623b16f6d17e6854b22ce8b725436a231a366a08..f1d912b9fd0d9798527a307e8822d243c6206f32 100644 (file)
--- a/iw.c
+++ b/iw.c
@@ -303,6 +303,7 @@ static int print_event(struct nl_msg *msg, void *arg)
        struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
        struct nlattr *tb[NL80211_ATTR_MAX + 1];
        char ifname[100];
+       __u8 reg_type;
 
        nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
                  genlmsg_attrlen(gnlh, 0), NULL);
@@ -323,6 +324,42 @@ static int print_event(struct nl_msg *msg, void *arg)
                printf("scan aborted on %s (phy #%d)\n",
                       ifname, nla_get_u32(tb[NL80211_ATTR_WIPHY]));
                break;
+       case NL80211_CMD_REG_CHANGE:
+
+               printf("regulatory domain change: ");
+
+               reg_type = nla_get_u8(tb[NL80211_ATTR_REG_TYPE]);
+
+               switch (reg_type) {
+               case NL80211_REGDOM_TYPE_COUNTRY:
+                       printf("set to %s by %s request",
+                              nla_get_string(tb[NL80211_ATTR_REG_ALPHA2]),
+                              reg_initiator_to_string(nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR])));
+                       if (tb[NL80211_ATTR_WIPHY])
+                               printf(" on phy%d", nla_get_u32(tb[NL80211_ATTR_WIPHY]));
+                       break;
+               case NL80211_REGDOM_TYPE_WORLD:
+                       printf("set to world roaming by %s request",
+                              reg_initiator_to_string(nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR])));
+                       break;
+               case NL80211_REGDOM_TYPE_CUSTOM_WORLD:
+                       printf("custom world roaming rules in place on phy%d by %s request",
+                              nla_get_u32(tb[NL80211_ATTR_WIPHY]),
+                              reg_initiator_to_string(nla_get_u32(tb[NL80211_ATTR_REG_INITIATOR])));
+                       break;
+               case NL80211_REGDOM_TYPE_INTERSECTION:
+                       printf("intersection used due to a request made by %s",
+                              reg_initiator_to_string(nla_get_u32(tb[NL80211_ATTR_REG_INITIATOR])));
+                       if (tb[NL80211_ATTR_WIPHY])
+                               printf(" on phy%d", nla_get_u32(tb[NL80211_ATTR_WIPHY]));
+                       break;
+               default:
+                       printf("unknown source (upgrade this utility)");
+                       break;
+               }
+
+               printf("\n");
+               break;
        default:
                printf("unknown event: %d\n", gnlh->cmd);
                break;
@@ -342,6 +379,7 @@ static int listen_events(struct nl80211_state *state,
                return -ENOMEM;
        }
 
+       /* Configuration multicast group */
        mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "config");
        if (mcid < 0)
                return mcid;
@@ -350,6 +388,7 @@ static int listen_events(struct nl80211_state *state,
        if (ret)
                return ret;
 
+       /* Scan multicast group */
        mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "scan");
        if (mcid >= 0) {
                ret = nl_socket_add_membership(state->nl_sock, mcid);
@@ -357,6 +396,14 @@ static int listen_events(struct nl80211_state *state,
                        return ret;
        }
 
+       /* Regulatory multicast group */
+       mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "regulatory");
+       if (mcid >= 0) {
+               ret = nl_socket_add_membership(state->nl_sock, mcid);
+               if (ret)
+                       return ret;
+       }
+
        /* no sequence checking for multicast messages */
        nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
        nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_event, NULL);
diff --git a/iw.h b/iw.h
index 7c2ab02c91c71b21802083a5777b9f2e294b4190..be35bd795f295e40d42f5ab8a4e30090a9c9943c 100644 (file)
--- a/iw.h
+++ b/iw.h
@@ -69,4 +69,6 @@ int ieee80211_frequency_to_channel(int freq);
 
 int nl_get_multicast_id(struct nl_sock *sock, const char *family, const char *group);
 
+char *reg_initiator_to_string(__u8 initiator);
+
 #endif /* __IW_H */
diff --git a/reg.c b/reg.c
index 74ae77f3229545d6524630e424180c5080b4fa5e..625d6953be4625b1ae9bbb0b37b2ad261af6a3a1 100644 (file)
--- a/reg.c
+++ b/reg.c
@@ -41,6 +41,22 @@ static bool is_world_regdom(char *alpha2)
        return false;
 }
 
+char *reg_initiator_to_string(__u8 initiator)
+{
+       switch (initiator) {
+       case NL80211_REGDOM_SET_BY_CORE:
+               return "the wireless core upon initialization";
+       case NL80211_REGDOM_SET_BY_USER:
+               return "a user";
+       case NL80211_REGDOM_SET_BY_DRIVER:
+               return "a driver";
+       case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+               return "a country IE";
+       default:
+               return "BUG";
+       }
+}
+
 static int handle_reg_set(struct nl_cb *cb,
                          struct nl_msg *msg,
                          int argc, char **argv)