How can I configure a DHCP server to assign addresses based on the OS that is running Solved maybe!

Marc Chamberlin marc at marcchamberlin.com
Wed Jun 2 02:28:11 UTC 2010


Thanks everyone for all your help, it gave me a lot to explore and was a 
big help. I have spent quite a few days on this, and though I hate 
throwing stones at a project, with as much invested in it as this one 
apparently has, and been around as long as it has, I am quite surprised 
at how difficult it is/was to work with and configure this server. I 
think a redesign, with particular attention paid to the model and 
configuration language should be seriously considered, but that is just 
IMHO.... Also, a number of (ok maybe I should say possible) bugs have 
surfaced during the course of my investigations, which made it far more 
difficult to find a solution, than it should have been. I will go 
through these and then present what I think is a solution and ask for 
opinions, since much of the underlying model is undocumented, (as far as 
I could find) in particular the precedence that is used by the server as 
it builds it's database and decision tree for IP address assignments.

First the problems I have discovered -

1. The biggest difficulty I had was trying to instrument my dhcpd.conf 
file with logging messages so as to determine what was happening when 
things went wrong. And frustratingly I discovered that logging ONLY 
works with the server successfully uses the configuration setup to 
assign an IP address. But when something goes wrong, and the server 
cannot assign an IP address to a client, it appears that the code simply 
drops to a fall through error message (which is very misleading) and 
none of the output from log statements is outputted! This is a very 
serious bug for users who are trying to set up their dhcp server, 
because when you most need help from instrumenting your configuration 
code, i.e. when a problem is occurring, the logging mechanism itself is 
broke also!  I finally discovered that nasty problem by putting a simple 
log statement at the very beginning of my dhcpd.conf file and 
discovering no output from it occurred whenever the dhcp server failed 
to find an IP address that it could assign to a client. But it always 
put out the log messages when it was successful in assigning an IP 
address! This failure forced me to work largely in the dark, with having 
to second guess a lot of possible causes as to why things were failing...

The fall through error message that I referred to seems to say " no free 
leases". I submit that this is wrong and misleading users, myself 
included. In actual fact the problem is the dhcp server could not assign 
a lease for an IP address due to the way the dhcpd.conf file is 
configured/mis-configured.

2. The hardware "object" while it may be convenient in some cases, I 
submit it is confusing and difficult to work with. The underlying data 
structure for this object is actually two fields, a hardware type 
identifier and a numeric encoded mac address. I don't understand the 
need to bond the hardware type with the mac address so tightly, and not 
provide any easier objects for users to work with and manipulate 
instead. It took me quite awhile to figure out how to use this object 
effectively, given my  goal of using the mac address of the client's 
interface in conditional expressions! See below..

3. The binary-to-ascii function does not match the format of mac 
addresses that the dhcp server displays in its own informational log 
statements. The main issue is that it does not put out leading zeros for 
small hexadecimal numbers, while mac addresses are shown in the log 
files with leading zeros. This prevents the user from doing a simple cut 
and paste of mac addresses from the log file and using that format in 
match statements within dhcpd.conf. This is a natural tendency on users 
part, and if the user is not aware of this difference it will cause 
confusion and a lot of time wasted in tracking down a problem caused by 
this difference.

4. There is not enough examples or descriptions on how to declare and 
use server variables within a dhcpd.conf file. I fooled around with all 
sorts of variants of what the following example attempts and could not 
find any solution to get this to work. It would have saved a lot of 
typing and made things more readable if it had worked...

macAddress =  binary-to-ascii(16, 8, ":", substring (hardware, 1, 6));
log (info, concat("Mac Address: ", macAddress));

BTW the following does work -

log (info, concat("Mac Address: ", binary-to-ascii(16, 8, ":", substring 
(hardware, 1, 6))));

5. In order to handle clients with more than one interface, and allow 
clients to dynamically switch between different interfaces, I included 
the following two statements in my dhcpd.conf file -

deny duplicates;
ping-check on;

My goal was to force a static IP address assignment to a particular 
client,  by using the class and pool declarations shown below, in 
conjunction with these declarations. I noted instead, that if a client 
booted up and initialized one of two interfaces (wired or wireless) then 
switched interfaces (disabling the first initialized interface in the 
process) that the dhcp server was unable to transfer the IP address 
assigned to the first interface to the second one based on a simple 
DHCPREQUEST. Instead the transfer only occurred if the client 
reinitialize his interface and forcing a DHCPDISCOVER instead.

Perhaps this is correct dhcp behavior, but I would think that doing a 
ping check and discovering that the client is no longer responding to 
it, would have been sufficient to prevent the user unfriendly 
requirement of having to reinitialize an interface just because it was 
hot-plugged and/or the user turned the other off. So I am confused!

---

That said, I set up a test network of a variety of clients, and after 
lots of experimentation I arrived at the following configuration 
segment, using classes and pools, to assign static IP addresses to 
clients based on their operating system and interfaces. This has the 
advantage of showing up in the logs, and if I am correct, gets around 
the limitations of using host declarations to assign static IP 
addresses. I won't show my entire dhcpd.conf file as most of it is 
pretty standard stuff, except for the two declarations I mentioned 
above. Sorry this is a bit long still, but I limited my test to just 5 
systems on a small network.....

class "marcslaptop_Vista_Class" {
    match if ((substring(option vendor-class-identifier, 0, 4) = "MSFT") and
             ((ucase(binary-to-ascii(16, 8, ":", substring (hardware, 1, 
6))) = ucase("0:1a:73:55:7d:f")) or
              (ucase(binary-to-ascii(16, 8, ":", substring (hardware, 1, 
6))) = ucase("0:16:36:c2:65:a4"))));
    log (info, "marcslaptop_Vista_Class matched");
}

class "marcslaptop_Linux_Class" {
#   match if (option dhcp-client-identifier = "\000marcslaptop") and
    match if ((substring(option dhcp-client-identifier,1,11) = 
"marcslaptop") and
             ((ucase(binary-to-ascii(16, 8, ":", substring (hardware, 1, 
6))) = ucase("0:1a:73:55:7d:f")) or
              (ucase(binary-to-ascii(16, 8, ":", substring (hardware, 1, 
6))) = ucase("0:16:36:c2:65:a4"))));
    log (info, "marcslaptop_Linux_Class matched");
}

class "nova_XP_Class" {
    match if (substring(option vendor-class-identifier, 0, 4) = "MSFT") and
             (ucase(binary-to-ascii(16, 8, ":", substring (hardware, 1, 
6))) = ucase("0:13:20:8e:59:41"));
    log (info, "nova_XP_Class matched");
}

class "nova_Linux_Class" {
    match if (option dhcp-client-identifier = "\000nova") and
             (ucase(binary-to-ascii(16, 8, ":", substring (hardware, 1, 
6))) = ucase("0:13:20:8e:59:41"));
    log (info, "nova_Linux_Class matched");
}

class "darkstar_2000_Class" {
    match if (substring(option vendor-class-identifier, 0, 4) = "MSFT") and
             (ucase(binary-to-ascii(16, 8, ":", substring (hardware, 1, 
6))) = ucase("0:e0:29:6d:fd:a3"));
    log (info, "darkstar_2000_Class matched");
}

class "stephslaptop_Vista_Class" {
    match if (substring(option vendor-class-identifier, 0, 4) = "MSFT") and
            (ucase(binary-to-ascii(16, 8, ":", substring (hardware, 1, 
6))) = ucase("0:1A:73:29:73:71"));
    log (info, "stephslaptop_Vista_Class matched");
}

class "teraserver_Class" {
    match if (ucase(binary-to-ascii(16, 8, ":", substring (hardware, 1, 
6))) = ucase("0:D:B:F7:0:6"));
    log (info, "teraserver_Class matched");
}

subnet 192.168.2.0 netmask 255.255.255.0 {
   default-lease-time 14400;
   max-lease-time 172800;
   pool {allow members of "marcslaptop_Linux_Class"; range  192.168.2.10;}
   pool {allow members of "marcslaptop_Vista_Class"; range  192.168.2.15;}
   pool {allow members of "nova_Linux_Class"; range  192.168.2.20;}
   pool {allow members of "nova_XP_Class"; range  192.168.2.25;}
   pool {allow members of "darkstar_2000_Class"; range  192.168.2.35;}
   pool {allow members of "stephslaptop_Vista_Class"; range  192.168.2.45;}
   pool {allow members of "teraserver_Class"; range  192.168.2.50;}
   pool {
         deny members of "marcslaptop_Linux_Class";
         deny members of "marcslaptop_Vista_Class";
         deny members of "nova_Linux_Class";
         deny members of "nova_XP_Class";
         deny members of "darkstar_2000_Class";
         deny members of "stephslaptop_Vista_Class";
         deny members of "teraserver_Class";
         deny known-clients;
         allow all clients;
         range 192.168.2.101 192.168.2.199;}
}

There are a few things of note in the pool declaration for the final 
pool segment that assigns IP addresses to unknown clients.

1. I added the deny members of "class" statements to prevent an IP 
address assignment to a client which activates a second interface. This 
requirement surprised me, but it seems to work.

2. The deny known-clients statement allows me to continue to use host 
declarations for systems which I will never have a problem identifying 
and making a static IP address assignment to.

3. The allow all clients statement is a guess on my part, as nothing is 
said about precedence of configuration statements in the documentation. 
But my guess is that this will allow assignment of an IP address to all 
unknown clients without my having to specify all clients on my network 
with host statements. If this won't work, and I have to use the allow 
unknown clients statement instead, then I would be right back to where I 
started from, having to specify hosts declarations, which I am trying to 
get around due to their inadequate capabilities. I have not yet fully 
tested this to my satisfaction, but initial trials seem to indicate it 
works....

I would welcome thoughts an feedback on whether this scheme will work or 
not. It is a bit messy and will be cumbersome to set up for a large 
network of users, but perhaps some scripts would ease the pain. At least 
the necessary information should be discoverable now, from the log and 
dhcpd.leases files, for me to manage the dhcp server without having to 
physically interact with each client computer..

     Marc..









-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 6464 bytes
Desc: S/MIME Cryptographic Signature
URL: <https://lists.isc.org/pipermail/dhcp-users/attachments/20100601/38c1d117/attachment.bin>


More information about the dhcp-users mailing list