Witness: fix whitespace
[metze/wireshark/wip.git] / ws80211_utils.c
index 5131f03bd796f3f1d321454940e53c997b6b6eab..8025e03f26ec16080161dab3e73ae4656ef59f00 100644 (file)
@@ -24,7 +24,7 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
 
-#include <config.h>
+#include "config.h"
 
 #include <stdio.h>
 
@@ -33,8 +33,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #include "ws80211_utils.h"
 
-#ifdef HAVE_LIBNL
-#include <strings.h>
+#if defined(HAVE_LIBNL) && defined(HAVE_NL80211)
+#include <string.h>
 #include <errno.h>
 #include <unistd.h>
 
@@ -106,28 +106,28 @@ int ws80211_init(void)
 static int error_handler(struct sockaddr_nl *nla _U_, struct nlmsgerr *err,
                         void *arg)
 {
-       int *ret = arg;
+       int *ret = (int *)arg;
        *ret = err->error;
        return NL_STOP;
 }
 
 static int finish_handler(struct nl_msg *msg _U_, void *arg)
 {
-       int *ret = arg;
+       int *ret = (int *)arg;
        *ret = 0;
        return NL_SKIP;
 }
 
 static int ack_handler(struct nl_msg *msg _U_, void *arg)
 {
-       int *ret = arg;
+       int *ret = (int *)arg;
        *ret = 0;
        return NL_STOP;
 }
 
 static int nl80211_do_cmd(struct nl_msg *msg, struct nl_cb *cb)
 {
-       int err;
+       volatile int err;
 
        if (!nl_state.nl_sock)
                return -ENOLINK;
@@ -138,9 +138,9 @@ static int nl80211_do_cmd(struct nl_msg *msg, struct nl_cb *cb)
 
        err = 1;
 
-       nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
-       nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
-       nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
+       nl_cb_err(cb, NL_CB_CUSTOM, error_handler, (void *)&err);
+       nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, (void *)&err);
+       nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, (void *)&err);
 
        while (err > 0)
                nl_recvmsgs(nl_state.nl_sock, cb);
@@ -156,28 +156,49 @@ struct nliface_cookie
        GArray *interfaces;
 };
 
+/*
+ * And now for a steaming heap of suck.
+ *
+ * The nla_for_each_nested() macro defined by at least some versions of the
+ * Linux kernel's headers doesn't do the casting required when compiling
+ * with a C++ compiler or with -Wc++-compat, so we get warnings, and those
+ * warnings are fatal when we compile this file.
+ *
+ * So we replace it with our own version, which does the requisite cast.
+ */
+
+/**
+ * nla_for_each_nested - iterate over nested attributes
+ * @pos: loop counter, set to current attribute
+ * @nla: attribute containing the nested attributes
+ * @rem: initialized to len, holds bytes currently remaining in stream
+ */
+#undef nla_for_each_nested
+#define nla_for_each_nested(pos, nla, rem) \
+       nla_for_each_attr(pos, (struct nlattr *)nla_data(nla), nla_len(nla), rem)
+
 static int get_phys_handler(struct nl_msg *msg, void *arg)
 {
        struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
-       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+       struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
 
-       struct nliface_cookie *cookie = arg;
+       struct nliface_cookie *cookie = (struct nliface_cookie *)arg;
 
        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 },
-               [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
+               {NLA_UNSPEC, 0, 0},             /* __NL80211_FREQUENCY_ATTR_INVALID */
+               {NLA_U32, 0, 0},                /* NL80211_FREQUENCY_ATTR_FREQ */
+               {NLA_FLAG, 0, 0},               /* NL80211_FREQUENCY_ATTR_DISABLED */
+               {NLA_FLAG, 0, 0},               /* NL80211_FREQUENCY_ATTR_PASSIVE_SCAN */
+               {NLA_FLAG, 0, 0},               /* NL80211_FREQUENCY_ATTR_NO_IBSS */
+               {NLA_FLAG, 0, 0},               /* NL80211_FREQUENCY_ATTR_RADAR */
+               {NLA_U32, 0, 0}                 /* NL80211_FREQUENCY_ATTR_MAX_TX_POWER */
        };
 
        struct nlattr *nl_band;
        struct nlattr *nl_freq;
-       struct nlattr *nl_cmd;
        struct nlattr *nl_mode;
        int bandidx = 1;
        int rem_band, rem_freq, rem_mode;
@@ -199,7 +220,7 @@ static int get_phys_handler(struct nl_msg *msg, void *arg)
        if (!cap_monitor)
                return NL_SKIP;
 
-       iface = g_malloc0(sizeof(*iface));
+       iface = (struct ws80211_interface *)g_malloc0(sizeof(*iface));
        if (!iface)
                return NL_SKIP;
 
@@ -207,15 +228,15 @@ static int get_phys_handler(struct nl_msg *msg, void *arg)
        iface->channel_types = 1 << WS80211_CHAN_NO_HT;
 
        if (tb_msg[NL80211_ATTR_WIPHY_NAME]) {
-               char *phyname;
-               phyname = g_strdup(nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME]));
-               iface->ifname = g_strdup_printf("%s.mon", phyname);
+               iface->ifname = g_strdup_printf("%s.mon",
+                nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME]));
        }
 
        nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) {
                bandidx++;
 
-               nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
+               nla_parse(tb_band, NL80211_BAND_ATTR_MAX,
+                         (struct nlattr *)nla_data(nl_band),
                          nla_len(nl_band), NULL);
 
 #ifdef NL80211_BAND_ATTR_HT_CAPA
@@ -232,7 +253,8 @@ static int get_phys_handler(struct nl_msg *msg, void *arg)
 
                nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {
                        uint32_t freq;
-                       nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),
+                       nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
+                                 (struct nlattr *)nla_data(nl_freq),
                                  nla_len(nl_freq), freq_policy);
                        if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
                                continue;
@@ -244,14 +266,19 @@ static int get_phys_handler(struct nl_msg *msg, void *arg)
                }
        }
 
-       /* Can frequency be set? */
+       /* Can frequency be set? Only newer versions of cfg80211 supports this */
+#ifdef HAVE_NL80211_CMD_SET_CHANNEL
        if (tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS]) {
                int cmd;
+               struct nlattr *nl_cmd;
                nla_for_each_nested(nl_cmd, tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS], cmd) {
                        if(nla_get_u32(nl_cmd) == NL80211_CMD_SET_CHANNEL)
                                iface->can_set_freq = TRUE;
                }
        }
+#else
+       iface->can_set_freq = TRUE;
+#endif
        g_array_append_val(cookie->interfaces, iface);
 
        return NL_SKIP;
@@ -286,7 +313,7 @@ static int get_freq_wext(const char *ifname)
 {
        int fd;
        int ret = -1;
-       /* Ugly hack to avoid incuding wireless.h */
+       /* Ugly hack to avoid including wireless.h */
        struct {
                char name1[IFNAMSIZ];
                __s32 m;
@@ -318,9 +345,9 @@ struct __iface_info
 
 static int get_iface_info_handler(struct nl_msg *msg, void *arg)
 {
-       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+       struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
        struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
-       struct __iface_info *iface_info = arg;
+       struct __iface_info *iface_info = (struct __iface_info *)arg;
 
        nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
                  genlmsg_attrlen(gnlh, 0), NULL);
@@ -334,10 +361,28 @@ static int get_iface_info_handler(struct nl_msg *msg, void *arg)
 
        if (tb_msg[NL80211_ATTR_WIPHY_FREQ]) {
                iface_info->pub->current_freq = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]);
-               iface_info->pub->current_chan_type = NL80211_CHAN_NO_HT;
+               iface_info->pub->current_chan_type = WS80211_CHAN_NO_HT;
 
-               if (tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE])
-                       iface_info->pub->current_chan_type =  nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
+               if (tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
+                       switch (nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE])) {
+
+                       case NL80211_CHAN_NO_HT:
+                               iface_info->pub->current_chan_type = WS80211_CHAN_NO_HT;
+                               break;
+
+                       case NL80211_CHAN_HT20:
+                               iface_info->pub->current_chan_type = WS80211_CHAN_HT20;
+                               break;
+
+                       case NL80211_CHAN_HT40MINUS:
+                               iface_info->pub->current_chan_type = WS80211_CHAN_HT40MINUS;
+                               break;
+
+                       case NL80211_CHAN_HT40PLUS:
+                               iface_info->pub->current_chan_type = WS80211_CHAN_HT40PLUS;
+                               break;
+                       }
+               }
 
        }
        return NL_SKIP;
@@ -387,7 +432,7 @@ int ws80211_get_iface_info(const char *name, struct ws80211_iface_info *iface_in
        __iface_info.type = -1;
        __iface_info.phyidx= -1;
        __iface_info.pub->current_freq = -1;
-       __iface_info.pub->current_chan_type = -1;
+       __iface_info.pub->current_chan_type = WS80211_CHAN_NO_HT;
 
        return __ws80211_get_iface_info(name, &__iface_info);
 }
@@ -420,6 +465,7 @@ static int ws80211_populate_devices(GArray *interfaces)
                ret = fgets(line, sizeof(line), fh);
                if (ret == NULL) {
                        fprintf(stderr, "Error parsing /proc/net/dev");
+                       fclose(fh);
                        return -1;
                }
        }
@@ -490,7 +536,7 @@ static int ws80211_create_on_demand_interface(const char *name)
 
        devidx = if_nametoindex(name);
        if (devidx)
-               return 0;
+               return ws80211_iface_up(name);
 
        if (sscanf(name, "phy%d.mon", &phyidx) != 1)
                return -EINVAL;
@@ -539,8 +585,14 @@ int ws80211_set_freq(const char *name, int freq, int chan_type)
 
        devidx = if_nametoindex(name);
 
+#ifdef HAVE_NL80211_CMD_SET_CHANNEL
        genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
                    0, NL80211_CMD_SET_CHANNEL, 0);
+#else
+       genlmsg_put(msg, 0, 0, nl_state.nl80211_id, 0,
+                   0, NL80211_CMD_SET_WIPHY, 0);
+#endif
+
        NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx);
        NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
 
@@ -623,7 +675,7 @@ int ws80211_frequency_to_channel(int freq)
 }
 
 int
-ws80211_str_to_chan_type(gchar *s)
+ws80211_str_to_chan_type(const gchar *s)
 {
        int ret = -1;
        if (!s)
@@ -640,7 +692,7 @@ ws80211_str_to_chan_type(gchar *s)
        return ret;
 }
 
-gchar
+const gchar
 *ws80211_chan_type_to_str(int type)
 {
        switch (type) {
@@ -674,7 +726,7 @@ int ws80211_get_iface_info(const char *name _U_, struct ws80211_iface_info *ifac
 
 void ws80211_free_interfaces(GArray *interfaces _U_)
 {
-};
+}
 
 int ws80211_frequency_to_channel(int freq _U_)
 {
@@ -686,13 +738,13 @@ int ws80211_set_freq(const char *name _U_, int freq _U_, int chan_type _U_)
        return -1;
 }
 
-int ws80211_str_to_chan_type(gchar *s _U_)
+int ws80211_str_to_chan_type(const gchar *s _U_)
 {
        return -1;
 }
 
-gchar *ws80211_chan_type_to_str(int type _U_)
+const gchar *ws80211_chan_type_to_str(int type _U_)
 {
        return NULL;
 }
-#endif /* HAVE_LIBNL */
+#endif /* HAVE_LIBNL && HAVE_NL80211 */