Mac OS X,  Mac OS X Server

Running DHCP on Mountain Lion Server

DHCP is one of the services that Apple has removed from its server product in the latest release, Mountain Lion Server. Given that the Server app and serveradmin command line tools no longer support using DHCP, it would seem on the outside that Apple no longer supports DHCP. However, when enabling Internet Sharing, the DHCP service is enabled and started. When this happens, a file called /etc/bootpd.plist is created and the LaunchDaemon located at /System/Library/LaunchDaemons/bootps.plist is configured to load and started.

When enabled using the Internet Sharing option in the Sharing System Preference pane, the DHCP pool is automatically configured to use the LAN IP scheme of the LAN adapter and NAT is enabled. DHCP can also be used for the NetInstall service, although it cannot be used at the same time that it is used for Internet Sharing, as per http://support.apple.com/kb/HT5412.

Upgrades from Lion Server will leave the DHCP configuration in place. However, most environments won’t want to install Lion and then upgrade to Mountain Lion in order to configure DHCP. Therefore, we can look at setting up DHCP manually, using a custom /etc/bootp.plist file. The way I’ve been doing this is to enable Internet Sharing and then disable it, which creates the bootpd.plist file in /etc. Once disabled again, you won’t be using the System Preference pane again to edit DHCP as doing so will destroy the custom bootpd.plist file we created.

Next, read the man page for bootpd:

man bootpd

Next, open /etc/bootpd.plist in your favorite text editor and make the following changes (if each is pertinent to you):

  • dhcp_enabled – Used to enable dhcp for each network interface. Replace the <false/> immediately below with <array> <string>en0</string> </array>. For additional entries, duplice the string line and enter each from ifconfig that you’d like to use dhcp on.
  • bootp_enabled – This can be left as Disabled or set to an array of the adapters that should be enabled if you wish to use the bootp protocol in addition to dhcp. Note that the server can do both bootp and dhcp simultaneously.
  • allocate – Use the allocate key for each subnet in the Subnets array to enable each subnet once the service is enabled.
  • Subnets – Use this array to create additional scopes or subnets that you will be serving up DHCP for. To do so, copy the entry in the array and paste it immediately below the existing entry. The entry is a dictionary so copy all of the data between and including the <dict> and </dict> immediately after the <array> entry for the subnet itself.
  • lease_max and lease_min – Set these integers to the time for a client to retain its dhcp lease
  • name – If there are multiple subnet entries, this should be unique and reference a friendly name for the subnet itself.
  • net_address – The first octets of the subnet followed by a 0. For example, assuming a /24 and 172.16.25 as the first three octets the entry would be 172.16.25.0.
  • net_mask – The subnet mask clients should have
  • net_range – The first entry should have the first IP in the range and the last should have the last IP in the range. For example, in the following example the addressing is 172.16.25.2 to 172.16.25.253.
  • dhcp_domain_name_server – There should be a string for each DNS server supplied by dhcp in this array
  • dhcp_domain_search – Each domain in the domain search field should be suppled in a string within this array, if one is needed. If not, feel free to delete the key and the array if this isn’t needed.
  • dhcp_router – This entry should contain the router or default gateway used for clients on the subnet, if there is one. If not, you can delete the key and following string entries.

An example file would look like the following:

<?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>NetBoot</key>
<dict/>
<key>Subnets</key>
<array>
<dict>
<key>allocate</key>
<false/>
<key>dhcp_bootfile_name</key>
<string>pxelinux/pxelinux.0</string>
<key>dhcp_domain_name</key>
<string>no-dns-available.example.com</string>
<key>dhcp_domain_name_server</key>
<array>
<string>10.5.20.5</string>
</array>
<key>dhcp_domain_search</key>
<array>
<string>no-dns-available.example.com</string>
</array>
<key>lease_max</key>
<integer>3600</integer>
<key>name</key>
<string>172.16.25 Subnet</string>
<key>net_address</key>
<string>172.16.25.0</string>
<key>net_mask</key>
<string>255.255.255.0</string>
<key>net_range</key>
<array>
<string>172.16.25.2</string>
<string>172.16.25.253</string>
</array>
<key>selected_port_name</key>
<string>vmnet8</string>
<key>uuid</key>
<string>2DC68B2E-9B49-46DF-A929-C9DF8918C77B</string>
</dict>
</array>
<key>allow</key>
<array/>
<key>bootp_enabled</key>
<false/>
<key>deny</key>
<array/>
<key>detect_other_dhcp_server</key>
<false/>
<key>dhcp_enabled</key>
<array>
<string>en0</string>
</array>
<key>old_netboot_enabled</key>
<false/>
<key>relay_enabled</key>
<false/>
<key>relay_ip_list</key>
<array/>
<key>reply_threshold_seconds</key>
<integer>0</integer>
</dict>
</plist>

To configure reservations, use the /etc/bootptab file. This file should have a column for the name of a computer, the hardware type (1), the hwaddr (the MAC address) and ipaddr for the desired IP address of each entry:

%%
# hostname hwtype hwaddr ipaddr bootfile
a.pretendco.com 1 00:00:00:aa:bb:cc 172.16.25.25
b.pretendco.com 1 00:00:00:aa:bb:cc 172.16.25.29

Once configured, fire it up using the following command:

sudo /bin/launchctl load -w /System/Library/LaunchDaemons/bootps.plist

And terminate using the following command:

sudo /bin/launchctl unload -w /System/Library/LaunchDaemons/bootps.plist

Once configured, configure the service to start automatically. To do so, open /System/Library/LaunchDaemons/bootps.plist. Here, just change the Disabled key to False, by changing the word True in line 6 to False.

<?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>Enabled</key>
<true/>
<key>Label</key>
<string>com.apple.bootpd</string>
<key>ProgramArguments</key>
<array>
<string>/usr/libexec/bootpd</string>
</array>
<key>inetdCompatibility</key>
<dict>
<key>Wait</key>
<true/>
</dict>
<key>Sockets</key>
<dict>
<key>Listeners</key>
<dict>
<key>SockServiceName</key>
<string>bootps</string>
<key>SockType</key>
<string>dgram</string>
<key>SockFamily</key>
<string>IPv4</string>
</dict>
</dict>
</dict>
</plist>

If there are any problems, add options to the booted daemon call. Here, most notably leverage the -v option to obtain more verbose entries in log files.