Netbooting on OSX SL Server

Once I got tftp working on IPv4, I still couldn’t get the Macbook client to download the boot or image files. Wireshark showed that the client didn’t get any file when it sent “acknowledge data block 0”. Nothing. So I installed tftp-hpa from Macports, hoping that would solve my problem, which it didn’t. But a few tips on that:

Install tftp-hpa using the “server” variant like so:

sudo port install tftp-hpa +server

Then go into the preference file (which isn’t in the same place as most plist files):

sudo pico /Library/LaunchDaemons/org.macports.tftpd.plist

…and remove the “-s” command line parameter, while changing the path to “/private/tftpboot/”. The “-s” parameter forced a chroot which won’t allow tftp to follow symlinks outside the given path, making netbooting impossible.

Then, and this is the crucial step, change the block size to max 512 by adding the “-B” option with the value “512”. What seemed to be happening in my installation is that the client requested a block size of 8192, the server approved it, and things just stopped working. Probably something to do with the switches I have, but crimping it to 512 fixed the problem. Of course, if you’re doing netbooting on a regular basis, or run diskless workstations, 512 may be intolerably slow, so then it could be worth experimenting with higher values.

I ended up with a plist file for tftp-hpa looking like this:

<?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>org.macports.tftpd</string>
<key>ProgramArguments</key>
<array>
        <string>/opt/local/bin/daemondo</string>
        <string>--label=tftpd</string>
        <string>--start-cmd</string>
        <string>/opt/local/sbin/tftpd</string>
        <string>-B</string>
        <string>512</string>
        <string>-L</string>
        <string>/private/tftpboot/</string>
        <string>;</string>
        <string>--pid=exec</string>
</array>
<key>Debug</key><false/>
<key>Disabled</key><true/>
<key>OnDemand</key><false/>
</dict>
</plist>

After modifying the file, stop and restart tftp-hpa by:

sudo launchctl unload /Library/LaunchDaemons/org.macports.tftpd.plist
sudo launchctl load -F /Library/LaunchDaemons/org.macports.tftpd.plist

It’s entirely possible I never needed to switch tftp servers from the default to tftp-hpa, but now I did, I don’t know if I’ve got the courage to switch back to try the original. Checking the man pages for the original tftpd server, I can find no setting for max block-size, so maybe tftp-hpa is necessary after all, just to be able to crimp the blocks enough.

OSX SL tftp doesn’t work?

…then this may be the reason… took me hours to figure out. Had to get it going for a netboot project, and the netboot just kept circling around the boot image download without getting much anywhere. First, check out Bombich’s troubleshooting, which put me on the right track without actually giving me the solution, but maybe that’s because my particular problem is relatively new. It may have been introduced with Snow Leopard.

What happened in my case is that I was able to download an image using the form:

tftp myserver.local
get NetBoot/NetBootSP0/Netinstall.nbi/i386/booter

…but not using the form:

tftp 172.25.26.27
get NetBoot/NetBootSP0/Netinstall.nbi/i386/booter

even though the “myserver.local” name pointed to the IP 172.25.26.27. At least, that’s what I presumed until I whipped out Wireshark and found out that using the “myserver.local” name resolved to an IPv6 address, not the IPv4 address I expected.

Next, I ran this on the server:

sudo lsof -i :69

COMMAND PID USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
launchd   1 root  144u  IPv6 0x0a9ab4a0      0t0  UDP *:tftp

Aha! The tftp server only runs IPv6 for some reason. That explains it.

To fix this, go into the tftp.plist file with pico:

sudo pico /System/Library/LaunchDeamons/tftp.plist

and add the optional key for IPv4 a bit down:

...
<key>Sockets</key>
<dict>
    <key>Listeners</key>
    <dict>
        <key>SockServiceName</key>
        <string>tftp</string>
        <key>SockType</key>
        <string>dgram</string>
        <key>SockFamily</key>
        <string>IPv4</string>
    </dict>
</dict>
...

After that, all you need to do is stop and restart tftp:

sudo launchctl unload /System/Library/LaunchDaemons/tftp.plist
sudo launchctl load -w /System/Library/LaunchDaemons/tftp.plist

Then check that the port is working on IPv4 as well:

COMMAND PID USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
launchd   1 root  144u  IPv6 0x0a9ab4a0      0t0  UDP *:tftp
launchd   1 root  150u  IPv4 0x07e2ee14      0t0  UDP *:tftp

After that, retry the tftp get command using both IPv4 and “myserver.local” addressing. Should work now. I must admit I don’t understand why IPv6 keeps working, though. Oh well, not that it bothers me, but it bothers me a little bit.

Update: this post is correct, but it still didn’t solve my problem, so please see next blog post for more, at least if you’re doing netboot stuff on Snow Leopard