Running new dhcpd instance on same physical interface

sthaug at nethelp.no sthaug at nethelp.no
Sun Aug 2 10:00:42 UTC 2009


> > Provided all of the server activity is IP unicast, there is a (seldom
> > used, often broken, and poorly documented) way to build the DHCP
> > server to "USE_SOCKETS" (#define in includes/site.h).  With this build
> > method, the server can not be guaranteed to be RFC 2131 compliant in
> > messages it can receive or transmit (raw sockets work around that for
> > us).
> 
> It would be nice if USE_SOCKETS or a similar mechanism could become
> "first class citizens" - then those of us with clients exclusively 
> behind relay agents could drop all broadcast handling etc.

I now several DHCP servers running on my FreeBSD box, bound to several
different IP addresses on the same physical interface. I tried this
once before, but got lost in a twisty little maze of code.

I needed several dhcpd's on the same physical interface because a few
of my clients shouldn't have the domain name/name servers that the rest
want (in fact they shouldn't have any at all), and ISC DHCP has no way
to "unset" a configuration parameter, as mentioned by Dave Hankins in

   https://lists.isc.org/pipermail/dhcp-users/2008-April/006173.html


This time I followed the inspiration of Christof Chen in

  https://lists.isc.org/pipermail/dhcp-hackers/2009-March/001781.html

Note that this assumes that your dhcpd's do *not* need to handle any
broadcast traffic (i.e. all your DHCP clients are behind relay agents).

What you need to do, then, is:

1. Edit includes/site.h to define USE_SOCKETS and USE_BPF_HWADDR:

-/* #define USE_SOCKETS */
+#define USE_SOCKETS
+#define USE_BPF_HWADDR

2. Run your usual ./configure

3. Edit generated includes/config.h to get rid of USE_BPF definition:

 /* Define to 1 to use the Berkeley Packet Filter interface code. */
-#define USE_BPF ""
+/* #define USE_BPF "" */

4. Patch common/bpf.c with patch included at the end of this message.

5. Compile and install dhcpd.

6. Edit your dhcpd.conf to include the "local-address" configuration
parameter.

7. And then you can run several dhcpd's on the same machine.

There is another issue which is still not covered, namely OMAPI. If you
define an omapi-port it will still be bound to INADDR_ANY, so only one
of your dhcpd's on the same machine can use OMAPI. In my case this was
not a significant limitation (but it is a limitation that should be easy
to fix if necessary).

As an aside, since dhcpd wants an interface parameter, it might be nice
if, when USE_SOCKETS is defined, dhcpd simply used the IP address of this
interface instead of needing the "local-address" configuration parameter.
This can be done with a one-line change to if_register_socket():

--- common/socket.c.orig	2008-08-29 19:48:57.000000000 +0200
+++ common/socket.c	2009-08-01 16:04:32.000000000 +0200
@@ -158,7 +158,7 @@
 		addr->sin_family = AF_INET;
 		addr->sin_port = local_port;
 		memcpy(&addr->sin_addr,
-		       &local_address,
+		       &info->addresses[0].s_addr,
 		       sizeof(addr->sin_addr));
 #ifdef HAVE_SA_LEN
 		addr->sin_len = sizeof(*addr);

I am, however, not at all sure that this is the best way to solve the
"problem".

In any case, below is the necessary patch to bpf.c.

Steinar Haug, Nethelp consulting, sthaug at nethelp.no
----------------------------------------------------------------------
--- common/bpf.c.orig	2007-08-23 11:49:51.000000000 +0200
+++ common/bpf.c	2009-07-31 13:36:42.000000000 +0200
@@ -34,7 +34,7 @@
 
 #include "dhcpd.h"
 #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)	\
-				|| defined (USE_LPF_RECEIVE)
+	|| defined (USE_LPF_RECEIVE) || defined(USE_BPF_HWADDR)
 # if defined (USE_LPF_RECEIVE)
 #  include <asm/types.h>
 #  include <linux/filter.h>
@@ -55,7 +55,7 @@
 #include "includes/netinet/if_ether.h"
 #endif
 
-#ifdef USE_BPF_RECEIVE
+#if defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR)
 #include <ifaddrs.h>
 #endif
 
@@ -547,7 +547,9 @@
 		interface_dereference (&fbi, MDL);
 	}
 }
+#endif /* USE_BPF_RECEIVE */
 
+#if defined (USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR)
 void
 get_hw_addr(const char *name, struct hardware *hw) {
 	struct ifaddrs *ifa;
@@ -603,4 +605,4 @@
 
 	freeifaddrs(ifa);
 }
-#endif
+#endif /* defined (USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR) */



More information about the dhcp-users mailing list