How to make dhcpd send NAKs instead of silently ignoring DHCPREQUESTS?

Andre Albsmeier Andre.Albsmeier at siemens.com
Wed Apr 4 05:28:44 UTC 2012


On Tue, 03-Apr-2012 at 09:04:34 +0200, Simon Hobson wrote:
> Andre Albsmeier wrote:
> 
> >I have a client (WinXP Professional)
> 
> Well, enough said. We've had people at work with related problems 

Yes ;-)

> where their laptop has failed to work out that it's moved between 
> their home and our office networks. I think I had them change the 
> subnet on their home network to be different to ours.
> 
> >  > There is potentially another way to do things.
> >>  The ISC server now supports reserved leases - these are "normal"
> >>  leases but even if expired will never be re-allocated to other
> >>  clients. If you create reserved leases for your fixed address clients
> >>  instead of using host statements then the addresses cannot be given
> >>  to anything else and will result in a NACK in the circumstances you
> >>  describe. You can either just extend your main range, or add small
> >>  ranges to just include the addresses in question.
> >
> >But from what I have seen I have to hack the dhcpd.leases file
> >for this. (BTW, I found this possibility before but found it
> >quite ugly so I decided to ask on the list ;-)).
> 
> I believe you can also do it via OMAPI - but I've never used it myself.
> 
> >In my personal opinion (I am no DHCP expert, just a user with the
> >above observations) I think that if a server is authoritative one
> >should be able to NAK unknown client's DHCPREQUESTs for addresses
> >not in dynamic ranges.
> 
> It's valid for there to be multiple, independent, authoritative DHCP 
> servers on a network as long as they have non-overlapping ranges. 

Yes, sure. I just _thought_ that if I am responsible for, let's
say, subnet 192.168.10.0/24 I should be able to control this
in a way that lets me clearly decide between:

1. if known client -> give him his known and fixed address
2. if unknown client -> be sure he gets an address in a
   specific range.

> Unless you tell the server that an address is explicitly not 
> available, it will remain silent regarding those it's not responsible 
> for.

That's what I have learned now ;-(. Again, in my eyes it should
be possible to tell the server: Yes, you are responsible for
subnet 192.168.10.0/24 _entirely_ and _alone_ and you NAK
everything that is not fixed and wants something not in the
dynamic range.

> It's just unfortunate that you've found a corner case where it is 
> valid to have a fixed-address and a dynamic range which overlap.

Right, but I use a different approach now. The patch below NAKs
requests from unknown clients that want to use an address outside
the dynamic range. No idea if it is correct but it seems to do
the trick. Just, in case anyone else is interested...


--- ./includes/dhcpd.h.ORI	2011-12-31 00:17:04.000000000 +0100
+++ ./includes/dhcpd.h	2012-04-03 14:08:29.000000000 +0200
@@ -713,6 +713,9 @@
 # define SV_LDAP_TLS_RANDFILE           77
 #endif
 #endif
+#define SV_AA_NAK_UNKNOWN		78
+
+extern unsigned char AA_nak_unknown;
 
 #if !defined (DEFAULT_PING_TIMEOUT)
 # define DEFAULT_PING_TIMEOUT 1
--- ./includes/dhctoken.h.ORI	2011-09-21 22:43:10.000000000 +0200
+++ ./includes/dhctoken.h	2012-04-03 14:09:41.000000000 +0200
@@ -364,6 +364,7 @@
 	GETHOSTBYNAME = 665,
 	PRIMARY6 = 666,
 	SECONDARY6 = 667
+	, AA_NAK_UNKNOWN = 668
 };
 
 #define is_identifier(x)	((x) >= FIRST_TOKEN &&	\
--- ./server/stables.c.ORI	2011-10-14 21:49:48.000000000 +0200
+++ ./server/stables.c	2012-04-03 14:11:13.000000000 +0200
@@ -266,6 +266,7 @@
 	{ "ldap-tls-randfile", "t",		&server_universe,  77, 1 },
 #endif /* LDAP_USE_SSL */
 #endif /* LDAP_CONFIGURATION */
+	{ "nak-unknown", "f",			&server_universe,  78, 1 },
 	{ NULL, NULL, NULL, 0, 0 }
 };
 
--- ./server/confpars.c.ORI	2011-07-01 13:58:53.000000000 +0200
+++ ./server/confpars.c	2012-04-03 14:29:19.000000000 +0200
@@ -4104,6 +4104,10 @@
 		code = SV_LEASEQUERY;
 		break;
 
+	      case AA_NAK_UNKNOWN:
+		code = SV_AA_NAK_UNKNOWN;
+		break;
+
 	      default:
 		parse_warn (cfile, "expecting allow/deny key");
 		skip_to_semi (cfile);
--- ./server/dhcpd.c.ORI	2011-12-31 01:55:22.000000000 +0100
+++ ./server/dhcpd.c	2012-04-03 14:24:18.000000000 +0200
@@ -157,6 +157,8 @@
 #endif /* NSUPDATE */
 int ddns_update_style;
 
+unsigned char AA_nak_unknown = 0;
+
 const char *path_dhcpd_conf = _PATH_DHCPD_CONF;
 const char *path_dhcpd_db = _PATH_DHCPD_DB;
 const char *path_dhcpd_pid = _PATH_DHCPD_PID;
@@ -1135,6 +1137,10 @@
 		data_string_forget(&db, MDL);
 	}
 
+	AA_nak_unknown = 0;
+	if( (oc = lookup_option( &server_universe, options, SV_AA_NAK_UNKNOWN )) != 0 )
+	  AA_nak_unknown = evaluate_boolean_option_cache( NULL, NULL, NULL, NULL, options, NULL, &global_scope, oc, MDL );
+
 	/* Don't need the options anymore. */
 	option_state_dereference (&options, MDL);
 	
--- ./server/dhcp.c.ORI	2012-04-03 14:26:20.000000000 +0200
+++ ./server/dhcp.c	2012-04-03 14:25:46.000000000 +0200
@@ -676,6 +676,10 @@
 		ack_lease (packet, lease, DHCPACK, 0, msgbuf, ms_nulltp,
 			   (struct host_decl *)0);
 	} else
+	    if( AA_nak_unknown ) {
+		log_info( "%s: unknown lease %s, sending NAK.", msgbuf, piaddr( cip ));
+		nak_lease( packet, &cip );
+	    } else
 		log_info ("%s: unknown lease %s.", msgbuf, piaddr (cip));
 
       out:


More information about the dhcp-users mailing list