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 1541RFC 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.