Monday, January 6, 2014

Automatic Location Switching in OSX Mavericks

I have had this issue for a while, where I travel between different locations and hence use different networks to connect to, yet I have to manually switch between these locations and their proxies
After trawling the internet for many variant complicated solutions I came up with a simple combination of many solutions. Two files are required, which can be modified according to your network settings, placed in the specified directories.
/usr/local/bin/locationchanger.sh
#!/bin/bash

#Note: make shore the log directory exists or modify the script to create it or 
#change the path to log to another location if you want logging.
LOG_FILE="/usr/local/var/log/locationchanger.log"
[ ! -f "$LOG_FILE" ] && touch "$LOG_FILE"

#Comment this line out if you don't want logging.
exec &>$LOG_FILE

LOCATION=
sleep 2
#Create as many locations as you need giving them unique names. Make sure the 
#values are valid values as are found in the Network Preferences Location dropdown
Location_Work="WorkLocationNameGoesHere"
Location_Other="OtherLocationNameGoesHere"
Location_Custom="CustomLocationNameGoesHere"
Location_Automatic="Automatic"

#These SSIDs must be wifi and wired networks which your computer knows 
#about or connects to.
SSID_Work="WRK_NET"
SSID_OTHER="MUMS_INTERNET"
SSID_Custom="BNE_AIRPORT"

Proxy_Work="http://proxy.work.com:80"
Proxy_Custom="http://proxy.custom.com:8021"
No_Proxy=

CurrentLocation=`networksetup -getcurrentlocation`
SSID=`/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -I | grep ' SSID:' | cut -d ':' -f 2 | tr -d ' '`
echo `date` "New SSID found: $SSID"

#Customise the cases according to your need and what you want set or run. 
#I have only shown how we can set proxies where necessary.

case $SSID in
 $SSID_Work  ) 
    LOCATION="$Location_Work"
    export http_proxy="$Proxy_Work"
    export ALL_PROXY="$http_proxy"
    echo "http_proxy=$Proxy_Work"
   ;;
        $SSID_Other )
                  LOCATION="$Location_Other"
    export http_proxy="$No_Proxy"
    export ALL_PROXY="$http_proxy"
    echo "http_proxy=$No_Proxy"

        $SSID_Custom )
                  LOCATION="$Location_Custom"
    export http_proxy="$Proxy_Custom"
    export ALL_PROXY="$http_proxy"
    echo "http_proxy=$Proxy_Custom"

        *  )      # Default for all other networks
    LOCATION="$Location_Automatic"
    export http_proxy="$No_Proxy"
    export ALL_PROXY="$http_proxy"
    echo "Proxy disabled."
  ;;
esac
 
scselect $LOCATION
echo "Location changed to $LOCATION based on $SSID"
exit 0


After creating the /usr/local/bin/locationchanger.sh and modifying it accordingly run the following command to make it executable:
sudo chmod +x /usr/local/bin/locationchanger.sh

~/Library/LaunchAgents/LocationChanger.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>locationchanger</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/locationchanger.sh</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>/etc/resolv.conf</string>
        <string>/Library/Preferences/SystemConfiguration/NetworkInterfaces.plist</string>
        <string>/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
Run the following to start this list checking for network changes:
launchctl load ~/Library/LaunchAgents/LocationChanger.plist