Apple's airport utility
Jan 11, 2016 · 830 words · 4 minutes read
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
Set up a symlink
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:
DisconnectOnLogout=NO
Unable to retrieve JoinMode
JoinModeFallback=DoNothing
RememberRecentNetworks=YES
RequireAdminIBSS=NO
RequireAdminNetworkChange=NO
RequireAdminPowerToggle=NO
WoWEnabled=YES
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.
Serialization
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" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AUTH_LOWER</key>
<integer>1</integer>
<key>AUTH_UPPER</key>
<integer>8</integer>
<key>CHANNEL</key>
<integer>36</integer>
<key>CHANNEL_FLAGS</key>
<integer>1040</integer>
<key>NOISE_CTL_AGR</key>
<integer>-95</integer>
<key>NOISE_UNIT</key>
<integer>0</integer>
<key>RSSI_CTL_AGR</key>
<integer>-64</integer>
<key>RSSI_CTL_LIST</key>
<array>
<integer>-60</integer>
<integer>-68</integer>
<integer>-64</integer>
</array>
<key>RSSI_EXT_AGR</key>
<integer>0</integer>
<key>RSSI_EXT_LIST</key>
<array>
<integer>0</integer>
<integer>0</integer>
<integer>0</integer>
</array>
<key>RSSI_UNIT</key>
<integer>0</integer>
</dict>
</plist>
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,
"RSSI_CTL_LIST" : [
-56,
-59,
-56
],
"AUTH_UPPER" : 8,
"RSSI_EXT_AGR" : 0,
"RSSI_EXT_LIST" : [
0,
0,
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).
Scanning
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.