I cannot figure out how access points determine the signal power of nearby clients.

I haven't found this information in any of the WiFi packet tutorials, so I can only assume that the power information isn't coming from the client, but is determined by the access point.

I know an application called aircrack that can determine this information, but before I jump into that and dig around, I'd like an overview of how the power is calculated. My Google skills aren't that bad, so I am surprised that so far I've been unable to dig up any information about it. Surely if aircrack can do it, this information is out there!

I was hoping that the users here can point me in the right direction?

Regarding the bounty

I guess it's time to attempt to use a bounty. In your answers, please post all links you can find that would assist anyone in understanding how this power detection works. Specific information on how it is implemented in aircrack would be perfect!


As of now, using the aircrack-ng suite as an example, it looks like the power value is pulled from buf[2] in net_read(). I believe this value ultimately comes from net_cmd, which results in paired calls to net_send and net_get(). I think net_get() reads in whatever header information is sent due to the call to net_send(), and this header indicates how much data should be copied into the buffer buf[].

But now what I don't get is this -- it sure looks like buf[] gets filled by the call to net_read_exact(), which is just reading data from the socket. If this is the case, and if power is a driver detail, why is the power value in the buffer? If that buffer is indeed filled by the socket data, doesn't that imply that the power is sent by the client / station? I believe that the AP / driver is in charge of supplying the power info, just like everyone has said, but just don't get this part.

  • I always thought it had something to do with percentage of lost packages, but it seems to be done via hardware. – Alex May 25 '13 at 6:30
  • An AP does not need signal strengh level to do its job. – BatchyX May 25 '13 at 14:00
  • @BatchyX Some APs (e.g., by MikroTik) can be configured to disconnect clients if the signal strength falls below the specified threshold. This is intended to be used when covering the area with multiple APs with the same SSID, so that clients which have moved to a place better covered by another AP are forced to switch to a better AP. Without such forced disconnection client stations often try to keep the connection to the same AP as long as possible, but switch to a lower bit rate, which degrades service for all other clients using the same channel. – Sergey Vlasov May 25 '13 at 15:48
  • @SergeyVlasov: You can achieve the same thing by not advertising slower rates. – BatchyX May 25 '13 at 16:15

Actually, the application which determines this information is airodump-ng, not aircrack-ng. From the airodump-ng documentation, power levels are determined as:

PWR - Signal level reported by the card. Its signification depends on the driver [...]

Well, let's see if we can do better. Looking through the latest source code of the airodump-ng.c file, we see the power gets set in the dump_add_packet(...) function:

/* only update power if packets comes from
 * the AP: either type == mgmt and SA != BSSID,
 * or FromDS == 1 and ToDS == 0 */
if (...)
    ap_cur->power_lvl[ap_cur->power_index] = ri->ri_power;

After digging through several layers of abstraction, structs, and function pointers, I found that this data is filled from the function linux_read(...) defined in the osdep/linux.c file. This is where the ri_power variable in the ri struct is filled with data, and indeed it does appear to be driver specific.

Most drivers follow the Radiotap standard (as opposed to the older prism54 standard detailed below), which have several predefined fields for determining antenna power, noise, and attenuation. These fields are used directly by airodump-ng to fill in the ri_power variable. Some of these are already available in decibel or power values.

airodump-ng will use either the antenna signal field (in dBm) or the dB antenna signal field (in dB) to compute the displayed signal power. Similar steps are used for the other fields, as they are all predetermined in the Radiotap specification linked to above. For example, the ri_power using the dB Antenna Signal field can be computed as:

    if(!got_signal) {
        if( *iterator.this_arg < 127 )
            ri->ri_power = *iterator.this_arg;
            ri->ri_power = *iterator.this_arg - 255;

        got_signal = 1;

As mentioned earlier, some devices follow the (older) prism54 specification (instead of Radiotap), which uses a fixed-length header. In this case, the RX power directly from the buffer (note this is not complete source code, just shows the paths taken to fill ri_power):

if (tmpbuf[7] == 0x40)
    ri->ri_power = tmpbuf[0x33];
    ri->ri_power = *(unsigned int *)( tmpbuf + 0x5C );
  • Thanks, I was referring to aircrack as a suite, and not the application specifically. I should have updated my question after digging through its source code. I am using airserv-ng and airodump-ng, and since it running on openwrt, ri_power is set in net_read() in network.c. I saw radiotap today, but don't think that data is used by the openwrt-specific implementation. I have been tracing backwards to figure out where buf[2] is set, since this is where the power value comes from. I believe the magic happens in net_get(). Would you mind telling me if you think I'm on the right track here? – Dave May 26 '13 at 6:53
  • I was going to edit your answer, but figured that I shouldn't, just in case -- I think you meant that airodump-ng will use the antenna fields, since airmon-ng is only used to put the interface into monitor mode. – Dave May 26 '13 at 6:56
  • And thank you for providing a really nice answer so far -- I don't think I've found anything like it on the net yet. :) I feel like I'm close to nailing this, but just need a little more advice, I think. – Dave May 26 '13 at 6:57
  • @Dave regarding your second comment, good catch. I edited the answer, but this is Super User - you are more than welcome to edit other people's posts as well :) Regarding net_read(), I did see some mention of that, but thought it was only used in the fall-back cases where the driver isn't detected as a WLAN (or isn't Radiotap/prism54). I will do some more digging around, but you do sound like you're on the right track. Might want to fire up airodump-ng under gdb and set a breakpoint in that function to make sure that's the one the function call dereferences. – Breakthrough May 26 '13 at 16:49
  • Unfortunately, I don't have gdb set up yet through Eclipse to be able to set breakpoints... that might take a little work. I'm running the code on a router and have found information on how to do it, but haven't gotten it to work yet. When you say the driver isn't detected as a WLAN, more specifically are you saying that option mode in /etc/config/wireless is not set to AP? – Dave May 27 '13 at 5:15

I'm not quite sure what you are asking.

Access points have radio receivers, naturally, and those receivers have analog sections with automatic gain, from which the hardware can derive a received signal strength. The hardware driver then makes this information available to other software in an OS-dependent way.

This is why aircrack makes a big deal about drivers and hardware.

  • Yes, that's what I was trying to say in my question -- since it's not in the packet information, it must be a hardware-dependent thing. So the big question is -- what tools are available on a router that would allow me to determine the signal strength for any arbitrary client, associated or not? – Dave May 25 '13 at 8:03
  • Since it is not part of the Wi-Fi standard, there's no standard answer. The tools available totally depend on the specific router, drivers, and Wi-Fi radio hardware you have. – Old Pro May 25 '13 at 19:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.