DDNS Registration for Mac OS X Server v10.5

Posted by Brian on December 11, 2009

For some time, I have had a problem with Mac OS X 10.5 Server registering all the network interfaces with DNS when joined to an Active Directory network. This causes a variety of problems, such as clients downloading large files from the server over an Xsan metadata network instead of the ‘public’ network. That is obviously not good for performance!

A solution to the problem was reported by Apple in article HT3169, Mac OS X Server v10.5, 10.6: Preventing DDNS registration for multiple interfaces. Unfortunately, editing the /etc/smb.conf file as indicated in the article did not cause Samba to only register the addresses of the selected interfaces.

Some topics in Apple Discussions presented a work-around that involves replacing the /usr/bin/net command with a script that prevents Samba from registering any of the interface addresses with the DNS server. I didn’t like this approach, especially since the problem is fixed in Mac OS X Server v10.6 and porting the necessary changes to v10.5 would result in the server working as detailed in the Apple Support article.

The rest of this blog entry shows how to port the DNSD registration fix to Mac OS X v10.5.

Notice: These instructions are provided ‘as-is’, without any expressed or implied warranty. In no event will the author be held liable for any damages arising from its use.

If you have built open source software in the past, you should have no problem with building and installing a new Samba net command. If you would rather install a copy I have already built, jump down to Install Fixed Samba net to download and install it.

Install Xcode 3.1.4

Download and install the latest version of Apple’s developer tools for Mac OS X v10.5.

xcode314_2809_developerdvd.dmg

Install DarwinBuild

Use the following commands in the Terminal (/Applications/Utilities). Please note that you must be logged in with an administrator account and you will be prompted for your account password.

svn co http://svn.macosforge.org/repository/darwinbuild/releases/Darwin9 darwinbuild
cd darwinbuild
make
sudo make install

Download Samba Source

Now that the prerequisites for building Samba are in place, the sources for the versions of Samba that shipped with Mac OS X v 10.5.8 and v10.6 should be downloaded and uncompressed on your desktop.

Mac OS X v10.5.8 http://www.opensource.apple.com/tarballs/samba/samba-187.8.tar.gz
Mac OS X v10.6 http://www.opensource.apple.com/tarballs/samba/samba-235.tar.gz

Porting The Samba net Fix

I was able to track the problem down to the get_my_ip_address() function in the samba/source/utils/net_dns.c file. Here is what it looks like for Mac OS X v10.5.8:

int get_my_ip_address( struct in_addr **ips )
{
struct iface_struct nics[MAX_INTERFACES];
int i, n;
struct in_addr loopback_ip = *interpret_addr2("127.0.0.1");
struct in_addr *list;
int count = 0;

/* find the first non-loopback address from our list of interfaces */

n = get_interfaces(nics, MAX_INTERFACES);

if ( (list = SMB_MALLOC_ARRAY( struct in_addr, n )) == NULL ) {
return -1;
}

for ( i=0; i<n; i++ ) {
if ( nics[i].ip.s_addr != loopback_ip.s_addr ) {
memcpy( &list[count++], &nics[i].ip, sizeof( struct in_addr ) );
}
}
*ips = list;

return count;
}

Notice that get_interfaces is used, which returns a list of all the network interfaces. Now have a look at the same function in the Samba shipped with Mac OS X v10.6:

int get_my_ip_address( struct in_addr **ips )
{
int i, n;
struct in_addr loopback_ip = *interpret_addr2("127.0.0.0");
struct in_addr *list;
int count = 0;

/* find the first non-loopback address from our list of interfaces */

load_interfaces();
n = iface_count();

if ( (list = SMB_MALLOC_ARRAY( struct in_addr, n )) == NULL ) {
return -1;
}

for (i = 0; i < n; i++) {
struct interface *iface = get_interface(i);
if (ip4_mask_match(iface->ip, loopback_ip)) {
/* Skip addresses that are in the loopback network. */
continue;
}

memcpy(&list[count++], &iface->ip, sizeof(struct in_addr));
}

*ips = list;
return count;
}

There are quite a few differences, but the key one is that load_interfaces, iface_count, and get_interface are used instead of get_interfaces. These other functions respect the settings in the /etc/smb.conf file and results in the behavior Apple detailed in their support article.

You could just copy and paste the newer version of the function into the v10.5.8 code. An alternative would be to download this patch to your desktop.

samba_net_ddns_patch (1 KB)

Apply the patch with the following commands.

cd ~/Desktop/samba-187.8
patch -p0 < ~/Desktop/samba_net_ddns_patch

Building Samba

With the fix now ported to the old version of Samba, build it with these commands.

cd ~/Desktop/samba-187.8
make

After a short while, the build stops with an error:

/bin/sh: line 0: cd: /tmp/samba/source/Sources/samba/source: No such file or directory
make[1]: *** [autogen] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [lazy_install_source] Error 2

I am not sure why this error occurs (missing folder?), but trying again seems to work…

make

Now there is a long wait as Samba is built for multiple architectures.

Create a 32-bit Samba net

Use this command to create a 32-bit Samba net command for Mac OS X v10.5. I suppose the build process could be adjusted to not build for 64-bit architectures, but this works fine.

cd ~/Desktop
lipo -create -arch i386 /tmp/samba/source/Build/i386/bin/net \
             -arch ppc /tmp/samba/source/Build/ppc/bin/net -output net

Install Fixed Samba net

At this point, you are ready to install the fixed Samba net command. If you were one of those who decided to skip to this step, you can use the binary I have compiled using these instructions. Download the archive to your desktop and expand it.

samba_net_ddns_fixed.zip (2 MB)

Whether you downloaded the net command or built it yourself, the procedure to install it is the same. If you are working directly on your server, use the following commands:

sudo mv /usr/bin.net /usr/bin/net.orig
sudo cp ~/Desktop/net /usr/bin/net
sudo chown root:wheel /usr/bin/net
sudo chmod 0755 /usr/bin/net

If you need to install the net command in a server remotely, use something similar to these commands. Be sure to use the name of your server and administrator account where appropriate.

scp ~/Desktop/net administrator@server:/tmp/
ssh administrator@server
sudo mv /usr/bin.net /usr/bin/net.orig
sudo cp ~/Desktop/net /usr/bin/net
sudo chown root:wheel /usr/bin/net
sudo chmod 0755 /usr/bin/net

Edit /etc/smb.conf

Likely you have already followed the instructions in Apple’s article on how to restrict the server to only register the specified network interfaces in DNS. If not, use this command to begin editing the /etc/smb.conf file:

sudo nano /etc/smb.conf

Insert the following lines after the line ; END required configuration., making sure to specify the interfaces that you want registered. Notice that you can specify multiple interfaces by separating them with a space.

[global]
interfaces = en0 bond0
bind interfaces only = yes 

To save the file, press Control-O and then Return. Press Control-X to exit.

Update Server DNS Entries

Now that everything is in place, you can force Mac OS X Server to update the current DNS entries. In doing so, the ones you did not specify should be automatically removed. Run this command, specifying your Windows domain where indicated.

sudo /usr/bin/net -W DOMAIN -P ads dns register

Although the instructions presented here are primarily for Mac OS X Server, they may also work for client computers.