Apple's airport utility

Jan 11, 2016 · 830 words · 4 minutes read applenetworkingwpa2

Apple has used the name AirPort since 1999 on wireless products including routers and Wi-Fi cards. Additionally every Mac comes with an obscure utility called airport. The airport utility can do several things such as get/set preferences, create logs, and even sniff frames.

Gettings Around

The airport utility is buried in the system’s library folder. I added a symlink so that I can reference the utility without having to specify the full path every time I want to call it.

$ ln -s /System/Library/PrivateFrameworks/Apple80211.framework/Versions/\
Current/Resources/airport /usr/local/bin/

Checking and setting preferences

Now I can easily get my airport preferences from the terminal (airport prefs).

$ airport prefs
AirPort preferences for en0:

Unable to retrieve JoinMode

This is neat but not too exciting. You can also set preferences. For example if you’re moving around an office with several access points you might want to be connected to the one with the strongest signal (rather than the one you connected to first).

$ sudo airport prefs JoinMode=Strongest JoinModeFallback=KeepLooking

Current status

In addition to getting and setting preferences, it’s also easy to print the current wireless status for the network you’re connected to.

$ airport --getinfo
     agrCtlRSSI: -61
     agrExtRSSI: 0
    agrCtlNoise: -95
    agrExtNoise: 0
          state: running
        op mode: station
     lastTxRate: 867
        maxRate: 1300
lastAssocStatus: 0
    802.11 auth: open
      link auth: wpa2-psk
          BSSID: [redacted]
           SSID: [redacted]
            MCS: 9
        channel: 36,80

This is a little more interesting — we get basic information like the received signal strength indicator (RSSI), noise, state, operation mode, and even the modulation and coding scheme (MCS) index.


Converting to XML

The output above can be parsed pretty easily (just split on the colon and whitespace) but other output from airport is not guaranteed to be so well organized.

We can build on this by asking for the information to be serialized as a XML Property List (plist). This makes it “easy” to work with the data by putting it into a standard format.

$ airport --getinfo --xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "">
<plist version="1.0">

Unfortunately Apple’s XML plists are pretty terrible to work with for data analysis but a plist is still easier to work with than having to parse the human-readable version.

Converting to JSON

The trick is to convert the XML to a more convenient format such as JSON. Fortunately Apple supplies a utility called plutil that can, among other things, convert plists to JSON.

$ airport -I -x | cat | plutil -convert json -r -o - -- -
  "RSSI_UNIT" : 0,
  "AUTH_LOWER" : 1,
  "NOISE_UNIT" : 0,
  "CHANNEL_FLAGS" : 1040,
  "RSSI_CTL_AGR" : -57,
  "CHANNEL" : 36,
  "NOISE_CTL_AGR" : -95,
  "AUTH_UPPER" : 8,
  "RSSI_EXT_AGR" : 0,

Interestingly the information that is available when requesting XML seralized output is different than the human-readable version (for example no SSID or BSSID information).


The last cool feature of the airport utility is Wi-Fi broadcast scanning which displays nearby networks. More specfically a broadcast scan will show all of the non-hidden access points.

$ airport --scan
        SSID      BSSID RSSI CHANNEL HT CC SECURITY (auth/unicast/group)
  [redacted] [redacted] -80  132,+1  Y  -- WPA2(PSK/AES/AES)
  [redacted] [redacted] -57  108,+1  Y  -- WPA2(PSK/AES/AES)
  [redacted] [redacted] -71  10      Y  -- WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)
  [redacted] [redacted] -34  11      Y  US WPA2(PSK/AES/AES)
  [redacted] [redacted] -73  6       Y  US NONE
  [redacted] [redacted] -76  7       Y  -- WPA2(PSK/AES/AES)
  [redacted] [redacted] -83  6       Y  US WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)
  [redacted] [redacted] -56  6       Y  -- WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)
  [redacted] [redacted] -81  4       Y  -- WPA2(PSK/AES/AES)
  [redacted] [redacted] -67  2       Y  -- WPA2(PSK/AES/AES)
  [redacted] [redacted] -81  1       N  -- WEP
  [redacted] [redacted] -67  1       Y  -- WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)
  [redacted] [redacted] -65  1       Y  -- WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)
  [redacted] [redacted] -62  1       Y  -- NONE
  [redacted] [redacted] -87  157     Y  US NONE
  [redacted] [redacted] -75  153     Y  -- WPA2(PSK/AES/AES)
  [redacted] [redacted] -74  44,+1   Y  US WPA2(PSK/AES/AES)
  [redacted] [redacted] -49  36      Y  US WPA2(PSK/AES/AES)

If you want to serialize the output from a broadcast scan you’ll run into some trouble because the XML plist contains a few tags called ‘data’ that plutil doesn’t know how to handle. Checking the syntax with either xmllint or plutil doesn’t indicate a problem because the XML is correct, but plutil doesn’t know how to convert the ‘data’ type. I just replaced the ‘data’ tag with ‘string’ and then plutil handles the serialization just fine.

airport -s -x | sed 's/data/string/g' | cat | plutil -convert json -r -o - -- -

The XML serialization of the broadcast scan provides much more information than the human-readable version and replacing the ‘data’ tags allows us to convert it to JSON. From here it is pretty easy to play with the data.