2

On my little network, I have a simple device which is apparently using only bootp (as opposed to the dhcp extensions to bootp) for obtaining its address. My dhcpd.conf file looks something like this

class "user" {
    match if substring(hardware, 1, 3) = 00:01:02;
    log(info, "matched to a 3com";
}

class "controller" {
    # tried matching based on two different styles I've seen on the net
    #match if substring(hardware, 1, 3) = 00:a0:45;
    match if (binary-to-ascii(16, 8, ":", substring(hardware, 0, 4)) = "1:00:a0:45");
    log(info, "found a controller");
}

subnet 192.168.0.0 netmask 255.255.0.0 {
    pool {
        allow members of "user";
        range 192.168.0.20 192.168.0.99;
        log(info, "A user just attached");
    }            

    pool {
        allow members of "controller";
        # never more than 1 on the network at a time
        range 192.168.1.240;
        log(info, "Allocated to a pwr user");
    }
}

The dhcp server simply will not match to the pool it's supposed to. From the log

BOOTREQUEST from 00:a0:45:95:ce:14 via eth1: BOOTP from dynamic client and no dynamic leases

The device is DENIED for both classes. Using tcpdump and wireshark for comparing packet dumps from a laptop and the controller device (I temporarily made a class for an HP laptop, added that class to the pool used for "controller" and extended the range by 2 addresses), it seems the only difference is that the controller device is literally a bootp packet (i.e. it lacks the mandatory option 53 identifying dhcp type), and carries only option 255. The laptop was matched by dhcpd without using the binary-to-ascii conversion. Additionally, and curiously, the controller client IP header uses the IP address first allocated, 192.168.1.240, but in the bootp section of the packet, the ciaddr field is 0. If it believes it has a valid lease, shouldn't it reflect this in ciaddr?

Why is dhcpd failing to match the MAC address of this device?

2 Answers 2

1

I have found the answer to this problem and I wanted to post it. It turned out that it had nothing to do with how the patterns were being matched. In fact,

class "user" {
    match if substring(hardware, 1, 3) = 00:01:02;
    log(info, "matched to a 3com";
}

this is the correct syntax to match on hardware.

However, this was a case where the facts lead me to the wrong conclusion. After reviewing several RFC's regarding bootp and dhcp, it became apparent that the device in question lacked the mandatory DHCP Type option, from RFC 1541 section 3, making it a bootp only client. Thus, the fix came from something that I wouldn't have expected would be required. The range statement includes the modifier dynamic-bootp which states the IP range is for dhcp or bootp clients. However, I also needed allow dynamic bootp clients; in the pool as follows:

pool {
    allow dynamic bootp clients;
    allow members of "controller";
    # never more than 1 on the network at a time
    range dynamic-bootp 192.168.1.240;
    log(info, "Allocated to a pwr user");
}

I would have thought that this modifier would have been sufficient but it was not. I needed both to accomplish the task.

I hope this proves helpful to someone.

0

You need to convert the data in "hardware" before comparing it, and account its first element which indicates type. Try something like:

class "controller" {
    # binary-to-ascii deletes leading zeroes and makes everything lowercase!
    match if binary-to-ascii(16,8,":",substring(hardware, 0, 4)) = "1:0:a0:45";
    log(info, "found a controller");
}

But if it's only one device, why not just use a fixed address:

host controller-hostname {
    hardware ethernet 00:a0:45:95:ce:14;
    fixed-address 192.168.1.240;
}

Add "dynamic-bootp" to the pool:

pool {
    allow members of "controller";
    # never more than 1 on the network at a time
    range dynamic-bootp 192.168.1.240;
    log(info, "Allocated to a pwr user");
}
6
  • That's a great question. There's never more than one on the network at a time, but it's not always the same device. That's why the rule is made as you see it provided. Also, I have attempted what you proposed above but with the same result. I've edited my question and updated. I apologize for this. Jan 17, 2018 at 18:08
  • Added change to "controller" pool (the range specification).
    – Deathgrip
    Jan 17, 2018 at 18:23
  • I found from the folks at the ISC dhcp mailing list that the binary-to-ascii function truncates leading 0's. So the rule should be, match if binary-to-ascii(16,8,":",substring(hardware, 0, 4)) = "1:0:a0:45";. A very subtle difference. Jan 23, 2018 at 1:15
  • @AndrewFalanga Umm... my original answer has that exact match line... save the second 00 field.
    – Deathgrip
    Jan 23, 2018 at 23:16
  • Yes, you're correct. I added my comment because, according to what I was told on the ISC dhcpd support mailing list, the function binary-to-ascii truncates leading 0's. This means that matching against 1:00:a0:45 would fail because it's not 1:0:a0:45. Jan 24, 2018 at 23:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .