On DSL access networks that use DHCP to assign an IP address to the enduser, it is usual that some network element along the way acting as a DHCP relay stuffs a so-called 'relay agent information option' aka "option 82" into the DHCPDISCOVER packets. This option has several suboptions: "Agent Circuit ID" and "Agent Remote ID". One of those two usually uniquely identifies the 'circuit' the customer is connected to, such as a DSLAM port.
If you want to assign static IP addresses to your customers, it's very convenient to use this option as a unique identifier for that.
host client-name-1 { hardware ethernet 00:e0:4c:a7:ca:de; fixed-address 192.168.0.6; }Starting from ISC DHCPD version 4.2, you can match on agent.circuit-id as well, by using this syntax:
host client-name-1 { host-identifier option agent.circuit-id "dslam42.port22"; hardware ethernet 00:e0:4c:a7:ca:de; fixed-address 192.168.0.6; }Unfortunately, at this time, the "host-identifier option ..." statement only works with agent.circuit-id. If you want to match on more than just agent.circuit-id. for example if agent.circuit-id is not unique and you need to match on another option as well, you are out of luck.
However, if your agent.circuit-id is unique, and you are using ISC DHCPD version 4.2 or later, you can use this method, stop reading here, and leave this page :)
Still here? Okay, you're looking for the workaround. There is one, by not using the host statement at all. That also works for ISC DHCPD versions before 4.2. It looks like this:
stash-agent-options true; shared-network "networkname" { subnet 192.168.0.0 netmask 255.255.255.0 { option broadcast-address 192.168.0.255; option routers 192.168.0.1; option subnet-mask 255.255.255.0; # A customer. class "id-192.168.0.2" { match if option agent.circuit-id = "dslam42.port22"; } pool { allow members of "id-192.168.0.2"; range 192.168.0.2; } # And yet another one. class "id-192.168.0.5" { match if option agent.circuit-id = "dslam42.port29"; } pool { allow members of "id-192.168.0.5"; range 192.168.0.5; } } }With recent hardware, this scales up to a few thousand customers. The internal implementation in ISC DHCPD of classes is such that it scales in a non-linar way - O(N^2) or something. So suddenly you'll end up with dhcpd eating 100% CPU. This is ofcourse bad.
The only problem is .. you cannot assign a fixed-address based on a subclass, and there is no way to say "allow members of subclass bla" in for example a pool-statement.
I chose to implement a new syntax for the "allow members of" statement. The standard syntax is:
allow members of <class>;This is now extended to also allow this:
allow members of <class> <subclass>;So, to assign a static address to customers based on the circuit-id, you would configure the server like this:
stash-agent-options true; class "static-1" { spawn with option agent.circuit-id; } shared-network "networkname" { subnet 192.168.0.0 netmask 255.255.255.0 { option broadcast-address 192.168.0.255; option routers 192.168.0.1; option subnet-mask 255.255.255.0; # A customer. pool { allow members of "static-1" "dslam42.port22"; range 192.168.0.2; } # And yet another one. pool { allow members of "static-1" "dslam42.port29"; range 192.168.0.5; } } }This has been tested on a Xeon 2.8 Ghz server, it uses just a few percent of CPU with 40.000 DHCP clients.
Ofcourse you can, as usual, define multiple classes if you like- for example, one per DSLAM. Say that your DHCP relay agent stuffs the DSLAM name into agent.remote-id and the port number in agent.circuit-id. It is not sufficient to have one class and just spawn subclasses based on the circuit-id, you will have clashes as multiple DSLAMs use the same circuit-ids.
In that case, do something like this:
class "dslam1" { match if (substring(option agent.remote-id,0,6) = "dslam1"); spawn with option agent.circuit-id; } class "dslam2" { match if (substring(option agent.remote-id,0,6) = "dslam2"); spawn with option agent.circuit-id; } [....] pool { allow members of "dslam1" "port29"; range 192.168.10.20; } [....]Another solution would be something like (syntax not tested) :
class "static-1" { spawn with concat(option agent.remote-id,0,6), "_", agent.circuit-id); } [....] pool { allow members of "static-1" "dslam2_port29"; } }
This means that if the customers changes this device (places a new modem or router) the new device will not be able to get a lease, since it will get assigned the same IP address and that has already been leased.
So make sure that a) you keep the lease time short enough (I recommend 2 hours or 7200 seconds), and b) your helpdesk knows about this since customers will hit this issue. Put something like this in your config:
default-lease-time 7200; max-lease-time 7200;
You apply them by going into the ISC DHCPD source directory, then run something like:
patch -p1 < ../01-subclass
patch -p1 < ../02-log-agent-options
You probably do not need this patch. In fact, I'm quite sure you don't. Do not use this.
01-subclass patch
02-log-agent-options patch
I think the best option for support is to go to the ISC DHCP
users mailinglist at https://lists.isc.org/mailman/listinfo/dhcp-users and
mention this webpage. Perhaps there are other people there using
the same patches that can help you.
Miquel van Smoorenburg