-3

I'm using libnl3 and nl80211.h to get the available bands for a connected wireless interface.

When I try to compile I get error: invalid conversion from ‘void*’ to ‘nlattr*’. The IDE (CLion) is also complaining about the line nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) and says incompatible pointer type 'nlattr *' and 'void *'.

What is being seen as void *, is it pos = nla_data(nla) from /usr/include/libnl3/netlink/attr.h that is considered void *?

Compile Error:

/home/username/Documents/Development/appname/fs_nl80211Class.cpp: In function ‘int callback(nl_msg*, void*)’:
/usr/include/libnl3/netlink/attr.h:328:21: error: invalid conversion from ‘void*’ to ‘nlattr*’ [-fpermissive]
  for (pos = nla_data(nla), rem = nla_len(nla);
                     ^

The macro from the libnl3/netlink/attr.h file:

#define nla_for_each_nested(pos, nla, rem) \
    for (pos = nla_data(nla), rem = nla_len(nla); \
         nla_ok(pos, rem); \
         pos = nla_next(pos, &(rem)))

My Code:

static int callback(struct nl_msg *msg, void *arg) {

    genlmsghdr *gnlh = (genlmsghdr *) nlmsg_data(nlmsg_hdr(msg));

    struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
    struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];

    struct nlattr *nl_band;

    int rem_band;
    static int last_band = -1;
    static bool band_had_freq = false;

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

    if (tb_msg[NL80211_ATTR_WIPHY_BANDS]) {

        // macro from libnl3/netlink/attr.h
        nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) {
            if (last_band != nl_band->nla_type) {
                cout << ("Band %d:", nl_band->nla_type) << endl;
                band_had_freq = false;
            }
            last_band = nl_band->nla_type;

            nla_parse(tb_band,
                      NL80211_BAND_ATTR_MAX,
                      nla_data(nl_band),
                      nla_len(nl_band), NULL);

            if (tb_band[NL80211_BAND_ATTR_FREQS]) {
                if (!band_had_freq) {
                    cout << "Frequencies:" << endl;
                    band_had_freq = true;
                }
            }
        }
    }

    //nl_msg_dump(msg, stdout);

    return NL_SKIP;
}
insecure-IT
  • 2,068
  • 4
  • 18
  • 26
  • 1
    _"What am I doing wrong?"_ What the error message actually says. – πάντα ῥεῖ Jul 20 '16 at 20:57
  • 1
    You cannot use a `void*` when the argument type is `nlattr*`. You need to explicitly cast the `void*` to `nlattr*` before calling the function. Use `reinterpret_cast(arg)` to do the explicit cast. – R Sahu Jul 20 '16 at 21:02
  • Why haven't you posted the code that contains the line with the error? – Barmar Jul 20 '16 at 21:22
  • @Barmar are you referring to `/usr/include/libnl3/netlink/attr.h`? – insecure-IT Jul 20 '16 at 21:29
  • I suppose so. Is `nla_for_each_nested` a macro defined in that file? – Barmar Jul 20 '16 at 21:30
  • @Barmar, yes it is. I've added it. – insecure-IT Jul 20 '16 at 21:33
  • What is the return type of `nla_data()`? The error implies that it returns `void*`, and you're trying to assign that to `nl_band`, which is `nlattr*`. – Barmar Jul 20 '16 at 21:38
  • The problem seems to be that the header file was intended for use with C, not C++. C allows `void*` to be converted automatically to any other pointer type, but C++ doesn't. – Barmar Jul 20 '16 at 21:39
  • I was wondering if it had to do with c vs c++. I'm using `iw` source as a guide and I do believe it's written in c. – insecure-IT Jul 20 '16 at 21:43

1 Answers1

2

The issue was g++ is unable to compile code with nla_for_each_nested macro due to implicit type conversion from void* to nlattr*.

See link from libnl list:

http://lists.infradead.org/pipermail/libnl/2016-February/002096.html

The fix in the nla_for_each_nested macro was to add type casting for nla_for_each_nested macro.

Changed from:

for (pos = nla_data(nla), rem = nla_len(nla); \

To:

for (pos = (struct nlattr *) nla_data(nla), rem = nla_len(nla); \
insecure-IT
  • 2,068
  • 4
  • 18
  • 26