linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* nl80211 scanning from userspace
@ 2010-08-16 19:06 Christopher Piggott
  2010-08-16 19:13 ` Johannes Berg
  0 siblings, 1 reply; 12+ messages in thread
From: Christopher Piggott @ 2010-08-16 19:06 UTC (permalink / raw)
  To: linux-wireless

Hi,

I'm trying to figure out how to use nl80211 to scan.  The "iw" example
has been somewhat helpful, though the userspace header file nl80211
and /usr/include/netlink/*.h have been helpful.  I'm on an ubuntu
system, and I'm sorry to say that the libnl1-doc package has some
doxygen files in it that don't agree with the actual headers (function
prototypes differ, etc.) but it's enough to get at least some picture
of what's going on.

Here's what I have put together so far, in snippets:

Register callbacks for all messages:
    callbacks = nl_cb_alloc(NL_CB_DEFAULT);
    nl_cb_set_all(callbacks,  NL_CB_CUSTOM, rx, NULL);

Create a socket, allocate a cache.  I do error checking on each of
these calls to make sure they succeed, but I'm eliminating that here
for brevity:
    genl_connect(sock);
    cache = genl_ctrl_alloc_cache(sock);
    nl80211 = genl_ctrl_search_by_name(cache, cacheName);   /*
cacheName is "nl80211" */

Start building the message.  First build an SSID list with one entry
in it (empty string)
    struct nl_msg *ssids = nlmsg_alloc();
    nla_put_string(ssids, 0, "");

Next build the scan request message:
    struct nl_msg *msg = nlmsg_alloc();
    int flags = 0;
    int cmd = NL80211_CMD_TRIGGER_SCAN;
    genlmsg_put(msg, 0, 0, genl_family_get_id(nl80211), 0, flags, cmd, 0);
    /* append our ssid list to this message as a nested message */
    nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids)

Finally I send the request:
    int rc = nl_send_auto_complete(sock, msg);

>From this I found out that 32 bytes were sent (seems reasonable).
Unfortunately, what I get back is this:
  [HEADER] 16 octets
    .nlmsg_len = 52
    .nlmsg_type = 2 <ERROR>
    .nlmsg_flags = 0 <>
    .nlmsg_seq = 1282012377
    .nlmsg_pid = 30415
  [ERRORMSG] 20 octets
    .error = -22 "Invalid argument"
  [ORIGINAL MESSAGE] 16 octets
    .nlmsg_len = 16
    .nlmsg_type = 23 <0x17>
    .nlmsg_flags = 5 <REQUEST,ACK>
    .nlmsg_seq = 1282012377
    .nlmsg_pid = 30415

so, even following what iw's "scan.c" does I have somehow pieced the
request together incorrectly.

Questions:
1. Am I doing something obviously wrong?
2. Is this even the interface I should be using to do this?  (I need
to scan for all access points on a specific "hidden" SSID to retrieve
some information about their SNR.  It's a type of "site survey"
application for building contour maps of coverage).

I'm not sure what I'm doing next makes sense, either.  After I send
the scan request I wait 3 seconds then start reading like this:
    while(nl_recvmsgs(sock, callbacks) != 0)
    {
        printf("processed a result\n");
    }

I have registered my callback earlier; this seems to work because I
get the message (above) plus later an "Operation Not Supported"
message.  The operation is indeed supported, as it works with the
iwlist and iw command line tools.

--Chris

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: nl80211 scanning from userspace
  2010-08-16 19:06 nl80211 scanning from userspace Christopher Piggott
@ 2010-08-16 19:13 ` Johannes Berg
       [not found]   ` <AANLkTiniqFJzrWFzNJTxsF31EZfSTei89dbS2Ak4YDjH@mail.gmail.com>
  0 siblings, 1 reply; 12+ messages in thread
From: Johannes Berg @ 2010-08-16 19:13 UTC (permalink / raw)
  To: Christopher Piggott; +Cc: linux-wireless

On Mon, 2010-08-16 at 15:06 -0400, Christopher Piggott wrote:

> Start building the message.  First build an SSID list with one entry
> in it (empty string)
>     struct nl_msg *ssids = nlmsg_alloc();
>     nla_put_string(ssids, 0, "");

I think that has to be a 1 instead of 0, but I'm not entirely sure.

> Next build the scan request message:
>     struct nl_msg *msg = nlmsg_alloc();
>     int flags = 0;
>     int cmd = NL80211_CMD_TRIGGER_SCAN;
>     genlmsg_put(msg, 0, 0, genl_family_get_id(nl80211), 0, flags, cmd, 0);
>     /* append our ssid list to this message as a nested message */
>     nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids)

You're not telling it which interface should scan, this is handled
generically in iw.c, look for
	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx);

> Finally I send the request:
>     int rc = nl_send_auto_complete(sock, msg);
> 
> From this I found out that 32 bytes were sent (seems reasonable).
> Unfortunately, what I get back is this:
>   [HEADER] 16 octets
>     .nlmsg_len = 52
>     .nlmsg_type = 2 <ERROR>
>     .nlmsg_flags = 0 <>
>     .nlmsg_seq = 1282012377
>     .nlmsg_pid = 30415
>   [ERRORMSG] 20 octets
>     .error = -22 "Invalid argument"
>   [ORIGINAL MESSAGE] 16 octets
>     .nlmsg_len = 16
>     .nlmsg_type = 23 <0x17>
>     .nlmsg_flags = 5 <REQUEST,ACK>
>     .nlmsg_seq = 1282012377
>     .nlmsg_pid = 30415
> 
> so, even following what iw's "scan.c" does I have somehow pieced the
> request together incorrectly.
> 
> Questions:
> 1. Am I doing something obviously wrong?

You're also missing the interface as above.

> 2. Is this even the interface I should be using to do this?  (I need
> to scan for all access points on a specific "hidden" SSID to retrieve
> some information about their SNR.  It's a type of "site survey"
> application for building contour maps of coverage).

Yes, it does make sense.

> I'm not sure what I'm doing next makes sense, either.  After I send
> the scan request I wait 3 seconds then start reading like this:
>     while(nl_recvmsgs(sock, callbacks) != 0)
>     {
>         printf("processed a result\n");
>     }
> 
> I have registered my callback earlier; this seems to work because I
> get the message (above) plus later an "Operation Not Supported"
> message.  The operation is indeed supported, as it works with the
> iwlist and iw command line tools.

Maybe you should look at wpa_supplicant either for doing your thing, or
for the driver_nl80211.c code in it, which is more explicit than iw.

johannes


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: nl80211 scanning from userspace
       [not found]   ` <AANLkTiniqFJzrWFzNJTxsF31EZfSTei89dbS2Ak4YDjH@mail.gmail.com>
@ 2010-08-16 19:41     ` Johannes Berg
  2010-08-16 21:22       ` Christopher Piggott
  0 siblings, 1 reply; 12+ messages in thread
From: Johannes Berg @ 2010-08-16 19:41 UTC (permalink / raw)
  To: Christopher Piggott; +Cc: linux-wireless

[adding mailing list back]

On Mon, 2010-08-16 at 15:37 -0400, Christopher Piggott wrote:
> Thanks, I had missed that.  I assume I also have to specify the
> interface number for NL80211_CMD_GET_SCAN as well as
> NL80211_CMD_TRIGGER_SCAN, right?
> 
> What I get now is a "Success" on the TRIGGER but an "Operation not
> supported" on the GET.

Yes, but if that was the only thing missing you'd also get -EINVAL.
However, GET only supports dumping, you have to see how to do that,
which explains the -EOPNOTSUPP.

johannes


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: nl80211 scanning from userspace
  2010-08-16 19:41     ` Johannes Berg
@ 2010-08-16 21:22       ` Christopher Piggott
  2010-08-16 21:43         ` Johannes Berg
  0 siblings, 1 reply; 12+ messages in thread
From: Christopher Piggott @ 2010-08-16 21:22 UTC (permalink / raw)
  To: linux-wireless

It's hard to figure out what's going on sometimes.  I set up an error handler:

static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr
*err, void *arg) {
    printf("ERROR %s (%d)\n", strerror(err->error), err->error);
    return NL_SKIP;
}

which also returns -95 (operation not supported) just as you said.
So, I'll have to figure out what you mean by "dumping."

I did find this:

        mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "scan");

in iw:event.c and traced it to some code in iw:genl.c, a file that
starts out by commenting "This ought to be provided by libnl".  That
situation doesn't seem to have changed.

Is this the area of the code you mean when you say "dump" ?  That I
need to register myself to receive the scan results?

--C

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: nl80211 scanning from userspace
  2010-08-16 21:22       ` Christopher Piggott
@ 2010-08-16 21:43         ` Johannes Berg
  2010-08-16 21:55           ` Christopher Piggott
  0 siblings, 1 reply; 12+ messages in thread
From: Johannes Berg @ 2010-08-16 21:43 UTC (permalink / raw)
  To: Christopher Piggott; +Cc: linux-wireless

On Mon, 2010-08-16 at 17:22 -0400, Christopher Piggott wrote:
> It's hard to figure out what's going on sometimes.  I set up an error handler:
> 
> static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr
> *err, void *arg) {
>     printf("ERROR %s (%d)\n", strerror(err->error), err->error);
>     return NL_SKIP;
> }
> 
> which also returns -95 (operation not supported) just as you said.
> So, I'll have to figure out what you mean by "dumping."
> 
> I did find this:
> 
>         mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "scan");
> 
> in iw:event.c and traced it to some code in iw:genl.c, a file that
> starts out by commenting "This ought to be provided by libnl".  That
> situation doesn't seem to have changed.
> 
> Is this the area of the code you mean when you say "dump" ?  That I
> need to register myself to receive the scan results?

No, you need to use NLM_F_DUMP etc. Really, check wpa_supplicant :)

johannes


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: nl80211 scanning from userspace
  2010-08-16 21:43         ` Johannes Berg
@ 2010-08-16 21:55           ` Christopher Piggott
  2010-08-16 23:16             ` Christopher Piggott
  0 siblings, 1 reply; 12+ messages in thread
From: Christopher Piggott @ 2010-08-16 21:55 UTC (permalink / raw)
  To: linux-wireless

OHHH.  I am with you now.  I looked at driver_nl80211.c and somehow
had a blind spot  when it came to message NLM_F_DUMP.  I see it now,
and it's sending me back results.

I am tempted to write a slightly higher level API on top of some of
this, once I understand the semantics of all of this a little better.
I will search around first and see if any attempts have already been
made.

Thank you very much for pushing me in the right direction.

--Chris


On Mon, Aug 16, 2010 at 5:43 PM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> On Mon, 2010-08-16 at 17:22 -0400, Christopher Piggott wrote:
>> It's hard to figure out what's going on sometimes.  I set up an error handler:
>>
>> static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr
>> *err, void *arg) {
>>     printf("ERROR %s (%d)\n", strerror(err->error), err->error);
>>     return NL_SKIP;
>> }
>>
>> which also returns -95 (operation not supported) just as you said.
>> So, I'll have to figure out what you mean by "dumping."
>>
>> I did find this:
>>
>>         mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "scan");
>>
>> in iw:event.c and traced it to some code in iw:genl.c, a file that
>> starts out by commenting "This ought to be provided by libnl".  That
>> situation doesn't seem to have changed.
>>
>> Is this the area of the code you mean when you say "dump" ?  That I
>> need to register myself to receive the scan results?
>
> No, you need to use NLM_F_DUMP etc. Really, check wpa_supplicant :)
>
> johannes
>
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: nl80211 scanning from userspace
  2010-08-16 21:55           ` Christopher Piggott
@ 2010-08-16 23:16             ` Christopher Piggott
  2010-08-17  8:51               ` Johannes Berg
  0 siblings, 1 reply; 12+ messages in thread
From: Christopher Piggott @ 2010-08-16 23:16 UTC (permalink / raw)
  To: linux-wireless

Forgive me if this is an obtuse question but why would one use
nl_socket_add_membership, if all that isn't necessary to get back the
scan results?

On Mon, Aug 16, 2010 at 5:55 PM, Christopher Piggott <cpiggott@gmail.com> wrote:
> OHHH.  I am with you now.  I looked at driver_nl80211.c and somehow
> had a blind spot  when it came to message NLM_F_DUMP.  I see it now,
> and it's sending me back results.
>
> I am tempted to write a slightly higher level API on top of some of
> this, once I understand the semantics of all of this a little better.
> I will search around first and see if any attempts have already been
> made.
>
> Thank you very much for pushing me in the right direction.
>
> --Chris
>
>
> On Mon, Aug 16, 2010 at 5:43 PM, Johannes Berg
> <johannes@sipsolutions.net> wrote:
>> On Mon, 2010-08-16 at 17:22 -0400, Christopher Piggott wrote:
>>> It's hard to figure out what's going on sometimes.  I set up an error handler:
>>>
>>> static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr
>>> *err, void *arg) {
>>>     printf("ERROR %s (%d)\n", strerror(err->error), err->error);
>>>     return NL_SKIP;
>>> }
>>>
>>> which also returns -95 (operation not supported) just as you said.
>>> So, I'll have to figure out what you mean by "dumping."
>>>
>>> I did find this:
>>>
>>>         mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "scan");
>>>
>>> in iw:event.c and traced it to some code in iw:genl.c, a file that
>>> starts out by commenting "This ought to be provided by libnl".  That
>>> situation doesn't seem to have changed.
>>>
>>> Is this the area of the code you mean when you say "dump" ?  That I
>>> need to register myself to receive the scan results?
>>
>> No, you need to use NLM_F_DUMP etc. Really, check wpa_supplicant :)
>>
>> johannes
>>
>>
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: nl80211 scanning from userspace
  2010-08-16 23:16             ` Christopher Piggott
@ 2010-08-17  8:51               ` Johannes Berg
       [not found]                 ` <AANLkTikzWs65zQYbCJQuvLv0e_010Rgy-C6J4ucpzBfa@mail.gmail.com>
  0 siblings, 1 reply; 12+ messages in thread
From: Johannes Berg @ 2010-08-17  8:51 UTC (permalink / raw)
  To: Christopher Piggott; +Cc: linux-wireless

On Mon, 2010-08-16 at 19:16 -0400, Christopher Piggott wrote:
> Forgive me if this is an obtuse question but why would one use
> nl_socket_add_membership, if all that isn't necessary to get back the
> scan results?

Well, you want to know when the scan finished, and for that you need to
be in the right group to receive the event when it finishes.

johannes



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Fwd: nl80211 scanning from userspace
       [not found]                 ` <AANLkTikzWs65zQYbCJQuvLv0e_010Rgy-C6J4ucpzBfa@mail.gmail.com>
@ 2010-08-20 23:42                   ` Christopher Piggott
  2010-08-21  9:21                     ` Johannes Berg
  2010-08-21 15:39                     ` Bob Copeland
  0 siblings, 2 replies; 12+ messages in thread
From: Christopher Piggott @ 2010-08-20 23:42 UTC (permalink / raw)
  To: linux-wireless

I'm sorry ... I hit REPLY again to Johannes personally rather than to
the list.  I don't know what it is about this list server that makes
me do it ... maybe there's no Reply-To.

Here was my followup question:


---------- Forwarded message ----------



I have another question about netlink scanning.  Here is what I am
doing.  First, trigger a request to starts canning:

   type = genl_family_get_id(nl80211);
   cmd = NL80211_CMD_TRIGGER_SCAN;
   flags = 0;
   pid = 0;
   (void) genlmsg_put(msg, pid, seqSent, type, 0, flags, cmd, 0);
   int dev = if_nametoindex("wlan0");
   nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev);
   rc = nl_send_auto_complete(sock, msg);


Wait a little while, and I get back a valid message that indicates the
scan is complete.  I handle that here:

bool try_parse_scan_status(struct nl_msg *msg) {
   struct genlmsghdr *genMsgHeader = (struct genlmsghdr *) nlmsg_data(header);

   /* check to make sure it's the right interface.  That works so
I'll leave that code out */
   switch (genMsgHeader->cmd) {
       case NL80211_CMD_NEW_SCAN_RESULTS:
           if (debug) {
               cerr << "New scan results available" << endl;
           }
           nl_msg_dump(msg, stdout);
           trigger_fetch_scan_results();
           break;
       /* other stuff deleted */
}

OK so here's what happens.  I get the message back indicating the scan
is complete, yay!  Then I try to call my trigger_fetch_scan_results().
 What that method does is sends command NL80211_CMD_GET_SCAN on that
interface, with the flag NLM_F_DUMP.  Great!

The problem is, I get a message back whose genMsgHeader->cmd STILL
says "NL80211_CMD_NEW_SCAN_RESULTS."  The resulting packet has good
stuff in it (the ssid, etc. info I am looking for).  UNFORTUNATELY,
because of the way I wrote my code it triggers another scan, which
causes it to say "Device or resource busy" and it just loops.


So here's the question: in my NL_CB_VALID listener, how do I
distinguish the response to the NL80211_CMD_TRIGGER_SCAN (the one that
indicates scan complete) from the response to the CMD_GET_SCAN (fetch
the results) message?

--Chris

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fwd: nl80211 scanning from userspace
  2010-08-20 23:42                   ` Fwd: " Christopher Piggott
@ 2010-08-21  9:21                     ` Johannes Berg
  2010-08-22 19:49                       ` Christopher Piggott
  2010-08-21 15:39                     ` Bob Copeland
  1 sibling, 1 reply; 12+ messages in thread
From: Johannes Berg @ 2010-08-21  9:21 UTC (permalink / raw)
  To: Christopher Piggott; +Cc: linux-wireless

On Fri, 2010-08-20 at 19:42 -0400, Christopher Piggott wrote:

> So here's the question: in my NL_CB_VALID listener, how do I
> distinguish the response to the NL80211_CMD_TRIGGER_SCAN (the one that
> indicates scan complete) from the response to the CMD_GET_SCAN (fetch
> the results) message?

One will be unicast to you, and the event is multicast to everybody. You
should be able to tell the difference.

johannes


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: nl80211 scanning from userspace
  2010-08-20 23:42                   ` Fwd: " Christopher Piggott
  2010-08-21  9:21                     ` Johannes Berg
@ 2010-08-21 15:39                     ` Bob Copeland
  1 sibling, 0 replies; 12+ messages in thread
From: Bob Copeland @ 2010-08-21 15:39 UTC (permalink / raw)
  To: Christopher Piggott; +Cc: linux-wireless

On Fri, Aug 20, 2010 at 7:42 PM, Christopher Piggott <cpiggott@gmail.com> wrote:
> I'm sorry ... I hit REPLY again to Johannes personally rather than to
> the list.  I don't know what it is about this list server that makes
> me do it ... maybe there's no Reply-To.

Tip: for most Linux-related mailing lists, simply use reply-to-all.

http://www.unicom.com/pw/reply-to-harmful.html

-- 
Bob Copeland %% www.bobcopeland.com

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fwd: nl80211 scanning from userspace
  2010-08-21  9:21                     ` Johannes Berg
@ 2010-08-22 19:49                       ` Christopher Piggott
  0 siblings, 0 replies; 12+ messages in thread
From: Christopher Piggott @ 2010-08-22 19:49 UTC (permalink / raw)
  To: linux-wireless

> One will be unicast to you, and the event is multicast to everybody. You
> should be able to tell the difference.

Oh, right ... or, is there some kind of "message source address" that
I can get to?  The only thing I have been able to figure out so far is
that the messages coming from the second message (multicast) seem to
have a PID of 0... maybe if I make sure mine is set to something else
I can tell that way.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2010-08-22 19:49 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-16 19:06 nl80211 scanning from userspace Christopher Piggott
2010-08-16 19:13 ` Johannes Berg
     [not found]   ` <AANLkTiniqFJzrWFzNJTxsF31EZfSTei89dbS2Ak4YDjH@mail.gmail.com>
2010-08-16 19:41     ` Johannes Berg
2010-08-16 21:22       ` Christopher Piggott
2010-08-16 21:43         ` Johannes Berg
2010-08-16 21:55           ` Christopher Piggott
2010-08-16 23:16             ` Christopher Piggott
2010-08-17  8:51               ` Johannes Berg
     [not found]                 ` <AANLkTikzWs65zQYbCJQuvLv0e_010Rgy-C6J4ucpzBfa@mail.gmail.com>
2010-08-20 23:42                   ` Fwd: " Christopher Piggott
2010-08-21  9:21                     ` Johannes Berg
2010-08-22 19:49                       ` Christopher Piggott
2010-08-21 15:39                     ` Bob Copeland

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).