== Configure subnet-specific options for shared networks

In the case that shared-networks are in use, with the pool containing
equally-valid IP addresses from multiple subnets, it is necessary to set the
subnet-specific parameters such as `DHCP-Router-Address`, `DHCP-Subnet-Mask`
and `DHCP-Broadcast-Address` based on the IP address that has been allocated.

Consider the ISC DHCP configuration snippet:

[source,iscdhcp]
----
option domain-name "example.org";

shared-network bigdept {

    option domain-name-servers 10.10.0.2, 10.10.0.3;
    default-lease-time 7200;

    subnet 10.30.10.0 netmask 255.255.255.0 {
        option routers 10.30.10.1;
    }
    subnet 10.30.20.0 netmask 255.255.255.0 {
        option routers 10.30.20.1;
    }
    range 10.30.10.10 10.30.10.254;
    range 10.30.20.10 10.30.20.254;

}
----

Or the equivalent Kea configuration:

[source,kea]
----
"Dhcp4": {
    "option-data": [
        { "name": "domain-name", "data": "example.org" }
    ],
    "shared-networks": [{
        "name": "bigdept",
        "option-data": [
            { "name": "domain-name-servers", "data": "10.10.0.2, 10.10.0.3" }
        ],
        "valid-lifetime": 7200,
        "subnet4": [{
            "subnet": "10.30.10.0/24",
            "pools": [ { "pool": "10.30.10.10 - 10.30.10.254" } ],
            "option-data": [
                { "name": "routers", "data": "10.30.10.1" }
            ]
        }],
        "subnet4": [{
            "subnet": "10.30.20.0/24",
            "pools": [ { "pool": "10.30.20.10 - 10.30.20.254" } ],
            "option-data": [
                { "name": "routers", "data": "10.30.20.1" }
            ]
        }]
    }],
    ...
}
----

As with the network to pool lookup, an instance of the `files` modules can be
employed (this time after the allocation of an IP address) to set the correct
reply parameters based on the subnet membership of the assigned address.

To do this, we can use this section of `<raddb>/mods-available/dhcp_files`:

[source,config]
----
files dhcp_subnets {
    filename = ${modconfdir}/files/dhcp
    key = "subnet"
}
----

Additionally, uncomment the `dhcp_subnets` policy in `<raddb>/policy.d/dhcp`.
This policy wraps the call to the `dhcp_subnets` files module with code that
"tightens" the `DHCP-Network-Subnet` attribute by setting it to the
just-allocated IP address.

The relevant entries in the `<raddb>/mods-config/files/dhcp` configuration
file might then look something like this:

[source,config]
----
network
        DHCP-Domain-Name := "example.org",
        Fall-Through := yes

network DHCP-Network-Subnet < 10.30.0.0/16, Pool-Name := "bigdept"
        DHCP-Domain-Name-Server := 10.10.0.2,
        DHCP-Domain-Name-Server += 10.10.0.3,
        DHCP-IP-Address-Lease-Time := 7200

subnet DHCP-Network-Subnet < 10.30.10.0/24
       DHCP-Router-Address := 10.30.10.1

subnet DHCP-Network-Subnet < 10.30.20.0/24
       DHCP-Router-Address := 10.30.20.1
----

=== Example packet processing

For our example, we consider a request arriving from a DHCP relay within
10.30.10.0/24. In the absence of any specific DHCP subnet selection options in
the request, the `DHCP-Network-Subnet` attribute is calculated to be the
relay's IP address, say 10.30.10.1.

The request is matched against the first "network" block, setting the domain
name to "example.org". By virtue of `Fall-Through` being set, the next "network"
block is considered.

Since the network identifier is within the specified subnet (i.e.  `10.30.10.1 <
10.30.0.0/16`) this second "network" block is matched. This block sets the pool
name to "bigdept", sets some network-specific DNS resolvers and sets the lease
time to 7200 seconds. `Fall-Through` is not set, so we are now done with
deriving the pool name and network options.

When the `dhcp_sqlippool` module is called during DHCP DISCOVER processing (in
`<raddb>/sites-enabled/dhcp`) the `bigdept` pool will be used for IP address
allocation.

After IP allocation the `dhcp_subnet` policy and files instance are called.
Before the subnet options are looked up the `DHCP-Network-Subnet`
attribute is tightened to match the assigned IP address, say 10.30.20.123.

The request does not match the first subnet block since 10.30.20.123 is not
within 10.30.10.0/24. However, the request does match the second subnet block
since `10.30.20.123 < 10.30.20.0/24`. This block sets the default gateway
reply parameter.  `Fall-Through` is not set, so we are now done with deriving
the pool name and network options.

The assigned IP address, network and subnet parameters will subsequently be
returned in the DHCP reply.

=== Testing the subnet-specific options

If you have set any subnet-specific reply parameters then you should test these
before proceeding further.

For example, in the case that you have a single, large pool spanning two IP
subnets you might want to test by repeatedly allocating addresses using sample
packets with different MAC addresses, each time checking to ensure that the
DHCP parameters correspond to the IP address that has been offered.

.Example output from dhcpclient showing a response
==================================================
 dhcpclient: ...
 ...
 ----------------------------------------------------------------------
 Waiting for DHCP replies for: 5.000000
 ----------------------------------------------------------------------
 ...
 DHCP-Your-IP-Address = 10.0.10.50
 DHCP-Router-Address = 10.0.10.1
 DHCP-Broadcast-Address = 10.0.10.255
 DHCP-Subnet-Mask = 255.255.255.255
==================================================


.Example output from dhcpclient showing a response
==================================================
 dhcpclient: ...
 ...
 ----------------------------------------------------------------------
 Waiting for DHCP replies for: 5.000000
 ----------------------------------------------------------------------
 ...
 DHCP-Your-IP-Address = 10.99.99.50
 DHCP-Router-Address = 10.99.99.1
 DHCP-Broadcast-Address = 10.99.99.255
 DHCP-Subnet-Mask = 255.255.255.255
==================================================


[TIP]
====
If the subnets are large then you might want to temporarily reduce their
size by setting the `status` field of the majority of the rows for each subnet
to "`disabled`" to cause offers to be made more readily with IP addresses in
different subnets.
====
