My Mac started working extremely slowly and I couldn't understand the reason for a while.
I knew my wireless was working seemingly without problems (iPad and iPhone working normally) but I thought to run the AirPort Utility to check out the wireless network.
My AirPort Extreme was reporting a problem. It turns out that I had changed my password on MobileMe to match iCloud, and of course my AirPort Extreme did not know that. It was trying to connect to the MobileMe servers with no success. I guess it was trying to connect to MobileMe non-stop and it was slowing down my system significantly. Fixing the password within the AirPort Extreme resolved the issue.
[crarko adds: It's always worth looking at network related issues when an unexpected slowdown happens. And when a transition happens (like the Mobile Me -> iCloud migration) expect to see issues like this happen. Fortunately they're easy to correct once identified.]
If you're like me, I'm frustrated by the way the Airport Utility displays NAT port mappings and DHCP assignments. I have a lot of ports mapped, and quite a few devices on my network and it's painful to remember which ports are mapped to which devices. I've searched high and low to find something to help and come up blank.
I wrote the following bash script which relies on the built-in utility PListBuddy to extract the relevant values from the property list that can be exported from the Airport Utility. To use it, open Airport Utility and select the device that has the mappings.
Press the 'Manual Setup' button (or Cmd+L) and the Utility will load the information from the device. Next choose Export Configuration File... from the file menu and save it to disk. Now run the bash script below and it will extract the values and send them to stdout in tab delimited form. You can then open the result in a spreadsheet or editor of your choice and see all your port mappings, DHCP assignments, known MAC addresses, current leases, and a snapshot of your network's performance.
It's isn't particularly pretty as I'm not a skilled bash writer, and someone with AppleScript expertise could do a much finer job. I'm always open to suggestions on how to do this. The hardest part is that there are no associative arrays in the version of bash that comes with OS X, so I had to do a lot of hashing and evals to create variables. Hope this proves useful and all comments and improvements are welcome.
Here's the script:
#!/bin/bash
##############################################################################
# Airport Configuration Reader
#
# This script processes the xml exported by the Airport Utility to produce a
# tab or comma delimited file containing the DHCP assignments, NAT port
# mappings, and a snapshot of the outstanding leases and performance of the
# wireless clients at the time the file was exported. The file is suitable
# for opening in excel or a text editor, where it can be formatted at will.
#
# It relies on the presence of the utility PlistBuddy, normally shipped with
# OS X, and displays an error message if it cannot find it.
#
# To use it, run the Airport Utility, select Manual Setup (command-L) and then
# File | Export Configuration to save the file on your disk. Then run this
# script against it.
#
# This has only been really tested on my Airport Extreme, which is a dual N.
# Unfortunately your mileage may vary as I don't have any other devices...
#
# Questions, bugs, suggestions, improvements: dan at gerrity dot org.
#
# $Source: /Users/dan/bin/RCS/apt2tsv-v $
# $Date: 2011-12-26 17:27:21-08 $
# $Revision: 1.12 $
#
###############################################################################
###############################################################################
# Variable and default definitions
#
# Default text item delimiter is a tab, the -c switch can be used for comma
# delimited. Note that string quoting is not provided so if names have quotes
# in them, the comma delimited version may not format exactly right.
declare -a res maps leases perf
me=$(basename $0)
delimiter="\t"
kma="${HOME}/.knownmacaddresses.$(date "+%Y-%m-%d_%H.%M")"
rev="$(echo '$Revision: 1.12 $' | sed -e 's/\$//g' -e 's/ $//' -e 's/R/r/')"
###############################################################################
# Functions
###############################################################################
function usage() {
[[ ${1} ]] && echo -e "Configuration file \"${1}\" could not be found.\n" 1>&2
echo -e "${me} ${rev}\n" 1>&2
echo -e "Usage: ${me} [-c] configuration[.baseconfig]\n" 1>&2
echo -e "Option -c creates comma delimited files instead of tab delimited.\n" 1>&2
echo "Using the AirPort Utility, select the device for which you want information, and" 1>&2
echo "then press the \"Manual Setup\" button. Once the configuration is loaded, use" 1>&2
echo "the File | Export Configuration File... to save the configuration to disk." 1>&2
echo -e "Use that file as the argument to the script.\n" 1>&2
exit 1
}
function checkForPlistBuddy() {
plb=$(which PlistBuddy)
[[ (! ${plb}) && (-e /usr/libexec/PlistBuddy) ]] && plb="/usr/libexec/PlistBuddy"
[[ ${plb} ]] && return
echo "PlistBuddy is an application provided by Apple that processes plist files."
echo "${me} relies on PListBuddy and it is neither in your path nor in the normal location"
echo "/usr/libexec/PlistBuddy."
exit 2
}
function getConfigFile() {
filepath="${1}:./${1}:./${1}.baseconfig"
filepath="${filepath}:${HOME}/${1}:${HOME}/${1}.baseconfig"
filepath="${filepath}:${HOME}/Downloads/${1}:${HOME}/Downloads/${1}.baseconfig"
filepath="${filepath}:${HOME}/Desktop/${1}:${HOME}/Desktop/${1}.baseconfig"
oIFS="${IFS}"
IFS=":"
for fpn in ${filepath}; do
if [[ -e "${fpn}" ]]; then cf="${fpn}"; break; fi
done
IFS="${oIFS}"
[[ ! -e "${cf}" ]] && usage "${cf}"
}
# This function makes a poor-man's lookup table (no associative arrays in bundled bash) between
# MAC address, IP address, and host name.
# Takes an environment variable name prefix, an address, and a description
function mungAddr() {
munged="${1}$(echo ${2} | sed -e 's/\./x/g' -e 's/:/x/g')"
shift; shift
eval "${munged}=\"$*\""
}
# Creates a 12 digit number for the IP address that is sortable
function ipSort() {
printf "%03s%03s%03s%03s" $(echo ${1} | sed 's/\./ /g')
}
# Gets some name and model parameters
function setName () {
n1=$(${plb} -c "print auNN" "${cf}")
[[ ${n1} ]] && name="${n1}"
n2=$(${plb} -c "print syDN" "${cf}")
n3=$(${plb} -c "print syAM" "${cf}")
if [[ (${n1}) && (${n2}) ]]; then
[[ "${n1}" != "${n2}" ]] && name="${n1}/${n2}"
else
[[ (${n1}) || (${n2}) ]] && name="${n1}${n2}"
fi
[[ (${name}) && (${n3}) ]] && name="${name}, ${n3}"
}
# Reads the DRes key to obtain dhcp reservations, also links machine name to IP and MAC addresses
function getReservations() {
resTitle="|Description|IP Address|MAC Address|Type"
numres=$(${plb} -c "print DRes:dhcpReservations:" "${cf}" | grep Dict | wc | awk '{print $1}')
for (( i=0; i<${numres}; i++ )); do
eval $(${plb} -c "print DRes:dhcpReservations:${i}" "${cf}" | grep "=" | \
sed -e 's/type/etype/' -e 's/[[:space:]]*\(.*\) = \(.*\)$/\1="\2"/')
macAddress=$(echo ${macAddress} | tr "[A-F]" "[a-f]")
mungAddr "i2h" "${ipv4Address}" "${description}"
mungAddr "m2h" "${macAddress}" "${description}"
mungAddr "m2i" "${macAddress}" "${ipv4Address}"
res[ i ]="$(ipSort ${ipv4Address})||${description}|${ipv4Address}|${macAddress}|${etype}"
done
}
# Reads the NAT address translations
function getMaps() {
mapTitle="|Description|Destination|Host|TCP Public|UDP Public|TCP Private|UDP Private|"
mapTitle="${mapTitle}Service Type|Service Name|Advertise|Enabled"
nummaps=$(${plb} -c "print fire:entries:" "${cf}" | grep Dict | wc | awk '{print $1}')
for (( i=0; i<${nummaps}; i++ )); do
dest=$(${plb} -c "print fire:entries:${i}:hosts:0" "${cf}")
hname="i2h$(echo ${dest} | sed 's/\./x/g')"
[[ "${!hname}" == "" ]] && host="** NO DHCP **" || host="${!hname}"
eval $(${plb} -c "print fire:entries:${i}" "${cf}" | grep "=" | grep -v hosts | \
sed -e 's/[[:space:]]*\(.*\) = \(.*\)$/\1="\2"/' -e 's/true/yes/g' -e 's/false/no/g')
maps[ i ]="$(ipSort ${dest})||${description}|${dest}|${host}|${tcpPublicPorts}|${udpPublicPorts}|${tcpPrivatePorts}|${udpPrivatePorts}|${serviceType}|${serviceName}|${advertiseService}|${entryEnabled}"
done
}
# Reads the outstanding leases at the time the export was made.
function getLeases() {
leaseTitle="|Host|IP Address|MAC Address|Lease Ends"
numleases=$(${plb} -c "print dhSL:leases:" "${cf}" | grep Dict | wc | awk '{print $1}')
for (( i=0; i<${numleases}; i++ )); do
eval $(${plb} -c "print dhSL:leases:${i}" "${cf}" | grep "=" | \
sed 's/[[:space:]]*\(.*\) = \(.*\)$/\1="\2"/')
macAddress=$(echo ${macAddress} | tr "[A-F]" "[a-f]")
leases[ i ]="$(ipSort ${ipAddress})||${hostname} (lease)|${ipAddress}|${macAddress}|${leaseEnds}"
done
}
function getPerformance() {
perfTitle="|Description|IP Address|MAC Address|Signal|Noise|Rate|Mode"
let perfEntries=0
numRadios=$(${plb} -c "print raSL" "${cf}" | grep "wlan.*" | wc | awk '{print $1}')
# for some reason the wlan entries are sparse, so just from from 0 to 9
# for (( rad=0; rad<${numRadios}; rad++ )); do
for (( rad=0; rad<9; rad++ )); do
numClients=$(${plb} -c "print raSL:wlan${rad}" "${cf}" 2> /dev/null | grep "macAddress" | wc | \
awk '{print $1}')
for (( j=0; j<${numClients}; j++)); do
eval macAddress=\"$(${plb} -c "print raSL:wlan${rad}:${j}:macAddress" "${cf}" 2> /dev/null | \
tr [A-F] [a-f])\"
for term in rssi noise txrate phy_mode; do
eval ${term}=\"$(${plb} -c "print raSL:wlan${rad}:${j}:${term}" "${cf}" 2> /dev/null)\"
done
mip="m2i$(echo ${macAddress} | sed 's/:/x/g')"
[[ ${!mip} ]] && ip=${!mip} || ip="0"
mdesc="m2h$(echo ${macAddress} | sed 's/:/x/g')"
[[ ${!mdesc} ]] && desc=${!mdesc} || desc="unknown"
perf[ (( perfEntries++ )) ]="$(ipSort ${ip})||${desc}|${ip}|${macAddress}|${rssi}|${noise}|${txrate}|${phy_mode}"
done
done
}
function printResults() {
echo "Airport Data taken from $(basename ${cf}) [${name}] on $(date)"; echo
echo "DHCP RESERVATIONS IN $(basename ${cf}) [${name}]"
echo ${resTitle} | tr "|" "${delimiter}"
printf "%s\n" "${res[@]}" | sort | cut -f2- -d'|' | tr "|" "${delimiter}"; echo
echo "DHCP LEASES IN $(basename ${cf}) [${name}]"
echo ${leaseTitle} | tr "|" "${delimiter}"
printf "%s\n" "${leases[@]}" | sort | cut -f2- -d'|' | tr "|" "${delimiter}"; echo
echo "NAT PORT MAPPINGS IN $(basename ${cf}) [${name}]"
echo ${mapTitle} | tr "|" "${delimiter}"
printf "%s\n" "${maps[@]}" | sort | cut -f2- -d'|' | tr "|" "${delimiter}"; echo
echo "PERFORMANCE SNAPSHOT IN $(basename ${cf}) [${name}]"
echo ${perfTitle} | tr "|" "${delimiter}"
printf "%s\n" "${perf[@]}" | sort | cut -f2- -d'|' | tr "|" "${delimiter}"; echo
}
function printKnownMacAddresses() {
echo "MAC ADDRESSES"
for (( i=0; i<${#res[@]}; i++ )); do
echo "${res[ i ]}" | sed 's/.*\|\(.*\)\|.*\|\(.*\)\|.*/\2 \1/' >> "${kma}"
done
for (( i=0; i<${#perf[@]}; i++ )); do
echo "${perf[ i ]}" | sed 's/^.*\|\(.*\)\|.*\|\(.*\)\|.*\|.*\|.*\|.*$/\2 \1/' >> "${kma}"
done
sort "${kma}" | uniq > "${kma}.tmp" && mv "${kma}.tmp" "${kma}"
lastmac=""
line=""
cat "${kma}" | while read mac rol; do
if [[ ${mac} == ${lastmac} ]]; then
line="${line}/${rol}"
else
[[ ${line} ]] && echo "$(echo ${line} | tr "|" "${delimiter}")"
line="${mac}|${rol}"
lastmac=${mac}
fi
done
}
###############################################################################
[[ ! ${1} ]] && usage
if [[ "${1}" == "-c" ]]; then
delimiter=","
shift
fi
while [[ "${1}" ]]; do
getConfigFile "${1}"
checkForPlistBuddy
setName
getReservations
getLeases
getMaps
getPerformance
printResults
shift
done
printKnownMacAddresses
[crarko adds: There are a couple of steps missing above. First, copy and paste the script to a text file and save it (I named mine 'airport_addr.sh'). I save it to my Desktop along with the exported Airport configuration file (named 'AC_Extreme.baseconfig' in my case). Then I opened Terminal and typed cd Desktop so the working directory is where the files are located. I made sure the script was executable by typing chmod +x airport_addr.sh.
To run the script I typed (use the actual names of your files instead of mine):
./airport1.sh AC_Extreme.baseconfig
The results displayed in the Terminal window. You'll probably want to redirect the output to a file to permanently capture the data, or you can just copy and paste the results from Terminal.]
To view this in Lion, just open a .mobileconfig file from Finder and System Preferences will now reveal 'Profiles' with a means to manage multiple profiles.
If you install a .mobileconfig, Profiles will remain available in System Preferences; if you delete all profiles, then Profiles no longer appears in System Preferences.
This doesn't yet seem to affect network access or browsing at all, so it is possible this feature exists to pave the way for more unified management of APN on desktops with mobile internet access, similar to iOS. You saw it here it first!
[crarko adds: I think the point of this is to indicate possible future support of cell networks in OS X, perhaps on a future MacBook Air. It doesn't seem to have any immediate utility.]
After upgrading to 10.7 my firewall logs were filled with endless "Firewall: Allow foo connecting from 1.2.3.4:1234 to port 1234 proto=x". Happily the logging system can be told to selectively ignore these messages.
Certain applications use lots of incoming network connections, and the default behaviour in Lion when the firewall is enabled is to log every single allowed connection.
A single rule line in /etc/asl.conf can silence these useless messages.
You can add this line using your favorite text editor, but you'll need one that can save files with root-level permissions (like the non-App Store version of TextWrangler).
[crarko adds: I haven't tested this one. To be honest, I don't run the OS X firewall.]
I needed to forcibly refresh the per user mcx for a large number of mobile users across many desktop machines under Snow Leopard so I wrote this short script that will do just that.
Can be run from remote desktop (as root), or locally (sudo). It will not always successfully refresh the mcx, but it will force it to be reloaded from the server on the next logon.
Here's the shell script:
#Brutally refresh mcx for a machine and all mobile accounts on it
#Clear machine cache
dscl . -list Computers | grep -v "^localhost$" | while read computer_name ; do sudo dscl . -delete Computers/"$computer_name" ; done
echo "Cleared machine MCX cache."
#Get a list of locally cached accounts
for usr in `dscl . -list /Users AuthenticationAuthority | grep LocalCachedUser | awk '{print $1}' | tr '\n' ' '`; do
#Clear mcx caches
dscl . -delete /Users/$usr MCXSettings
echo "Cleared MCXSettings for "$usr
dscl . -delete /Users/$usr MCXFlags
echo "Cleared MCXFlags for "$usr
dscl . -delete /Users/$usr cached_groups
echo "Cleared cached groups for "$usr
#Attempt to refresh from server
mcxrefresh -n $usr
echo "Refreshed preferences for "$usr; done
[crarko adds: MCX is the centralized Managed Client for Mac OS X. You use this from OS X Server. Typically this would be found in academic environments for managing shared machines in labs or in Mac-centric enterprises. For more information consult the documentation for OS X Server.]
In Finder, Command+K (Finder » Go » Connect to Server…) permits the storing of frequently used server addresses and protocols. However, when servers are indicated only by their IPv4 or IPv6 addresses, it is not easy to remember which address corresponds with which server. There appears to be no way to include text information associated with server addresses.
It is possible to include the # anchor at the end of the address and to indicate some information after this #. No spaces are allowed after the #.
Note that the true addresses have been changed of course in the examples.
[crarko adds: This works at least as far back as Leopard, and it wouldn't surprise me if it goes back further. I didn't find an obvious duplicate, but it's possible this has been mentioned before.]
AirDrop is a handy way to share files between Macs. Unfortunately, it is only supported on newer models which have the hardware necessary to support a certain type of point-to-point WiFi connection. There is, however, a hidden setting to enable AirDrop on older Macs. Just type:
into a Terminal window, hit enter, and relaunch the Finder.
Note that:
You must do this on both the sending and receiving macs, even if one of them already has the correct WiFi hardware (I think).
You will be able to see other macs on the same network, and they will be able to see your Mac (when AirDrop is open), even if they are not physically nearby. On a larger network with many Macs, this could potentially cause some confusion, although it shouldn't be a real security issue. This may be why Apple decided not to enable this feature by default.
Both macs must be connected to the same network somehow (ethernet, existing WiFi network, etc.)
[crarko adds: So here I sit, with only one Lion machine, so I can't fully test this. However, when using the command, it did enable the AirDrop icon in the Finder's Sidebar and said it had become available, so it will likely work, given the caveats mentioned above. To reverse this, just change the 1 in the command to a 0. This will be a great boon to those of us with some older (but still Lion-capable) machines still around.]
Lion ships with an app called Wi-Fi diagnostics. It allows you to monitor Wi-Fi networks your computer is connected to and collect various kinds of information. This utility could be very useful for finding problems or doing research on your Wi-Fi networks.
The easiest way to launch Wi-Fi Diagnostics is to open it directly from the location /System/Library/CoreServices.
Once it launches, you get some options to choose from. As an example, let's use the first, Monitor Performance. Select that and click Continue.
You are given a live-updating graph of the signal/noise ratio of your network. This could be useful for live testing to find problems with interference. For example, turn on your coordless phone and see if your ratio worsens. If it does, move your router farther away from the phone.
The other options are also useful, allowing you to log events like people connecting and disconnecting, and allowing you to sample raw data sent across the network.
[crarko adds: A good utility to have, with some very powerful capabilities. Use it responsibly, and also take it as a reminder not to send private data over unencrypted connections, because there are plenty of programs which can snoop open Wi-Fi networks.]
Many people, myself included seem to be having problems binding 10.7 machines into Active Directory, a cryptic 'Error 5202' seems to be fairly common. Here's the fix that worked on our network.
Initially I managed to get machines to bind by manually creating an edu.mit.Kerberos file and populating it before performing the actual bind. This would work but a reboot would often cause a 'Network Accounts Unavailable' message.
The opendirectoryd logs were full of messages such as 'No preferred destination' and 'Failed to retrieve keychain password for 'MACHINENAME$' module '' node '/Active Directory/DOMAIN'.'
On a whim I tried disabling IPv6 on the ethernet adapter -- which is apparently no longer possible using the GUI in 10.7. Once I disabled it from the command line the machine bound without the need to create a kerberos file and authentication worked perfectly.
You can disable IPv6 from the command line with:
networksetup -setv6off Ethernet
Alternatively the script below will disable it on all adapters:
#!/bin/sh
services=$(networksetup -listallnetworkservices | grep -v "*");
for service in "${services}"
do
echo "Disabling IPV6 on ${service}";
networksetup -setv6off "${service}";
done
exit 0
Note: I've read a few things that say that disabling IPv6 can cause problems but we don't use it on our network and I haven't had any issues yet.
[crarko adds: I haven't tested this one. Looking at the man page for the networksetup command gives -setv6automatic or -setv6manual as the parameters to enter to re-enable IPv6 using the above command.]
I'm experiencing a problem whereby the Windows shares I use at work mount in the Finder but don't reveal 'child of child' directories. So basically I can't see any of my working files/folders.
Here's a workaround I used in this situation:
Open Terminal, navigate to the share (once mounted) in /Volumes. Navigate to one of the child of child folders (they appear in Terminal but were empty when viewed in the Finder) and type 'open.'
This opens the folder in the Finder revealing the files/folders that were invisible before. In addition, you can now navigate 'up' in the Finder to see the previously hidden parent directory.