Add Static ARP Entry at Boot

I struggled a lot with Matthieu's solution since it caused two problems on my Mac OS X 10.9.2:

  1. Jobs in the LaunchAgents folder are executed using the current user. However arp needs to be executed using root.
  2. The arp-command is executed too early, when the network is not up. But the network is needed by the arp-command.

The first problem can be solved by storing the .plist file in LaunchDaemons instead of LaunchAgents. This will ensure that the command is executed as root.

The second problem is a bit tricky. Since launchd does not handle dependencies, we have to write our own shell script which first waits until the network is up an then execute the arp command. (See here)

So here is my solution:
First create/open the plist file using a text-editor:

sudo nano /Library/LaunchDaemons/local.arpentries.plist

Then paste the following content:

<?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>Label</key>
    <string>local.arpentries</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/arpentries</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <false/>
</dict>
</plist>

Set owner etc.:

sudo chown root:wheel /Library/LaunchDaemons/local.arpentries.plist
sudo chmod 0644 /Library/LaunchDaemons/local.arpentries.plist

Now create/open the shell script using a text editor

sudo nano /usr/local/bin/arpentries

Paste the following:

#!/bin/bash

# max number of retries
retries=10

# include Startup commons
. /etc/rc.common

# wait for network to become available
CheckForNetwork

while [ "$NETWORKUP" != "-YES-" ]
do
        retries=$((retries - 1))
        if [ $retries -le 0 ] ; then
                exit 1
        fi
        sleep 2
        NETWORKUP=
        CheckForNetwork
done

# set the static arp entries
arp -s 192.168.1.111 xx:xx:xx:xx:xx:xx

exit 0

And the rights:

sudo chmod 0744 /usr/local/bin/arpentries 

Launchd is a daemon that starts, stops and manages daemons, applications, processes, and scripts on OSX. It's intended to replace unix' cron.

Create a new .plist file :

<?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>local.arpentry</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/sbin/arp</string>
        <string>-s</string>
        <string>192.168.1.1</string>
        <string>00:00:00:00:00:00</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>Nice</key>
    <integer>10</integer>
    <key>KeepAlive</key>
    <false/>
</dict>
</plist>

Then move your new .plist to ~/Library/LaunchAgents so it will loaded every time you log into your session and therefore run you command everytime you log in.