# Assign common DHCP reply packet options dhcp_common { # The contents here are invented. Change them! update reply { &DHCP-Domain-Name-Server = 127.0.0.1 &DHCP-Domain-Name-Server += 127.0.0.2 &DHCP-Subnet-Mask = 255.255.255.0 &DHCP-Router-Address = 192.0.2.1 &DHCP-Broadcast-Address = 192.0.2.255 &DHCP-IP-Address-Lease-Time = 7200 &DHCP-DHCP-Server-Identifier = &control:DHCP-DHCP-Server-Identifier } } # Lookup DHCP group based options. This policy allows for membership # of multiple groups so can cover the ISC concepts of "group" and "class" # To use this enable the "dhcp_files" module #dhcp_group_options { # foreach &request:DHCP-Group-Name { # dhcp_set_group_options # } #} # Policy to override DHCP-Network-Subnet # # Some networks have a "shared-network" or "multinet" configuration (as # defined by some other DHCP servers) in which multiple IP subnets may # co-exist in a single Layer 2 network (or VLAN). # # In enterprise environments this is often for the purpose of providing loose # segregation between classes of devices such as local network-attached # storage or IP telephony. There are valid reasons why each of the subnets is # not seperately VLANed, such as to enable the use of ICMP redirects to avoid # hairpinning of cross-subnet traffic via a gateway. # # In ISP environments this is a common configuration for edge networks whose # access is provided by DOCSIS cable modems that share a VLAN with the devices # they provide a service to but are seperately addressed. # # Where it is necessary to force the selection of a particular subnet for a # device, multiple pools must be configured for each subnet and referenced # with unique identifiers in the *network-specific* section of # mods-config/files/dhcp. # # By default DHCP-Network-Subnet is populated such that it normally # refers to the Layer 2 network from which the DHCP query originates - we # cannot know the intended subnet for the device without additional input to # the policy. # # Override DHCP-Network-Subnet to be an address within the desired # network to force selection of a particular address pool and/or network # parameters. # # Note: If each subnet within a network is equally valid for the DHCP requests # originating from that network then you do not need to call this policy, # rather look at the examples concerning dhcp_subnet in # mods-config/files/dhcp instead, which use a single pool containing addresses # from all subnets then set the correct subnet-specific options based on the # randomly assigned IP address. # #dhcp_override_network { # if (&DHCP-Vendor-Class-Identifier && &DHCP-Vendor-Class-Identifier == "SIP100") # update request { # DHCP-Network-Subnet := 10.10.0.0 # } # } #} # Policy that calls the files instance of the same name after first making # DHCP-Network-Subnet specific to the allocated IP address of the client. #dhcp_subnet { # update { # &DHCP-Network-Subnet := "%{%{reply:DHCP-Your-IP-Address}:-%{DHCP-Client-IP-Address}}" # } # # # Call the dhcp_subnet instance of the files module # dhcp_subnet #} # Assign compatibility data to request for sqlippool for DHCP Request dhcp_sqlippool_request { # # During initial address selection (DORA) the REQUEST is broadcast and # requested-ip must be provided. We revoke any active offers for addresses # not matching the requested-ip, i.e. those made by other servers when # processing the DISCOVER. # # If there is only a single server then this optimisation can be disabled. # if (&DHCP-Requested-IP-Address) { update request { &Acct-Status-Type := Start } dhcp_sqlippool.accounting } # Extend an existing offer or active lease update request { &Acct-Status-Type := Alive } dhcp_sqlippool.accounting { notfound = return } update reply { &DHCP-Your-IP-Address := "%{%{DHCP-Requested-IP-Address}:-%{DHCP-Client-IP-Address}}" } } # Assign compatibility data to request for sqlippool for DHCP Release dhcp_sqlippool_release { # Do some minor hacks to the request so that it looks # like a RADIUS Accounting Stop request to the SQL IP Pool module. update request { &Acct-Status-Type = Stop } # Call the actual module in accounting context dhcp_sqlippool.accounting } # Assign compatibility data to request for sqlippool for DHCP Decline dhcp_sqlippool_decline { # Do a minor hack to the request so that it looks # like a RADIUS Accounting Off request to the SQL IP Pool module. update request { &Acct-Status-Type = Accounting-Off } # Call the actual module in accounting context dhcp_sqlippool.accounting } # Example policy for fetching option data from SQL dhcp_policy_sql { # # Network-specific options # # # We want to lookup the Layer 2 network specific DHCP options to # include in the reply. For this we need a stable identifier for the # network from which the request is originating (based on # DHCP-Network-Subnet) which can be used as the lookup key # (DHCP-SQL-Option-Identifier) for the network options. # # Here we fabricate an example for the purpose of placing all # configuration elements into SQL. We use a PostgreSQL query that # returns the network identifier in the row containing the smallest # enclosing CIDR, which assumes a schema such as the following: # # CREATE TABLE fr_network_to_identifier (network CIDR, network_id TEXT) # # Note: An rlm_files based lookup of the network_identifier (as per # the examples in the dhcp virtual server) may be preferable to an ad # hoc SQL query assuming that the network topology does not change # frequently. # # update control { # &control:Tmp-String-0 := "%{dhcp_sql:SELECT network_id \ # FROM fr_network_to_identifier \ # WHERE '%{DHCP-Network-Subnet}'::inet << network \ # ORDER BY MASKLEN(network) DESC LIMIT 1;}" # } # # Use the network identifer to lookup the options specific to the # originating network, using "network" context. Common network # settings can be placed into a group and shared, with individual # networks mapped to one or more option groups. # # - Place network-specific options in the dhcpreply table with # "context = 'network'". # - Add "Fall-Through := Yes" to the network options in the dhcpreply # table to trigger group lookups for the network, which are # disabled by default. # - Place "identifier = , groupname = , # priority = , context = 'network'" in the dhcpgroup # table to map a network to a shared set of network options. # - Place group-specific options in the dhcpgroupreply table with # "context = 'network'". # # Note: In "shared-network" or "multinet" topologies you can instead # just set all of the network options once in the subnet-specific # options (after obtaining an IP address), below. # # update control { # &DHCP-SQL-Option-Context := "network" # &DHCP-SQL-Option-Identifier := &control:Tmp-String-0 # } # dhcp_sql.authorize # # Allocate IPs from the DHCP pool in SQL. # # Here we simply reuse the network_id (obtained previously) as the # Pool-Name. # # update control { # &Pool-Name := &control:Tmp-String-0 # } # dhcp_sqlippool # # Subnet-specific options # # # In "shared-network" or "multinet" topologies (in which a Layer 2 # network has a single pool that contains addresses from multiple # subnets) it is necessary to set subnet-specific options based on the # address that has just been allocated. # # Again, for this we need to derive a stable identifier for the subnet # to which the IP address we are issuing belongs that will serve as a # lookup key for the network options. # # Continuing our previous example, we can use a PostgreSQL query to # find the subnet identifer in the row with the closest enclosing # CIDR, which assumes a schema such as the following: # # CREATE TABLE fr_subnet_to_identifier (subnet CIDR, subnet_id TEXT) # # Note: An rlm_files based lookup of the subnet_identifier (as per the # examples in the dhcp virtual server) is preferable to an ad hoc SQL # query assuming that the network topology does not change frequently. # # update control { # &control:Tmp-String-0 := "%{dhcp_sql:SELECT subnet_id \ # FROM fr_subnet_to_identifier \ # WHERE '%{reply:DHCP-Your-IP-Address}'::inet << subnet \ # ORDER BY MASKLEN(subnet) DESC LIMIT 1;}" # } # # Use the subnet identifer to lookup the options specific to the # subnet for the IP we are allocating, using "subnet" context. Common # subnet settings can be placed into a group and shared, with # individual subnets mapped to one or more option groups. # # - Place subnet-specific options in the dhcpreply table with # "context = 'subnet'". # - Add "Fall-Through := Yes" to the subnet options in the dhcpreply # table to trigger group lookups for the subnet, which are # disabled by default. # - Place "identifier = , groupname = , # priority = , context = 'subnet'" in the dhcpgroup # table to map a subnet to a shared set of subnet options. # - Place group-specific options in the dhcpgroupreply table with # "context = 'subnet'". # # update control { # &DHCP-SQL-Option-Context := "subnet" # &DHCP-SQL-Option-Identifier := &control:Tmp-String-0 # } # dhcp_sql.authorize # # Host-specific and group-specific options # # "Groups" conventionally differentiate devices based on manual # groupings using a device-specific identifier such as the MAC # address. # # - Place host-specific options in the dhcpreply table with # "context = 'group'". # - Add "Fall-Through := Yes" to the device options in the dhcpreply # table to trigger group lookups, which are disabled by default. # - Place "identifier = , groupname = , # priority = , context='group'" in the dhcpgroup table # to map a device to its groups. # - Place group-specific options in the dhcpgroupreply table with # "context = 'group'". # # update control { # &DHCP-SQL-Option-Context := "group" # &DHCP-SQL-Option-Identifier := &request:DHCP-Client-Hardware-Address # } # dhcp_sql.authorize # # Class/subclass-specific options # # # "Classes" conventionally differentiate devices based on all or part # of one or more DHCP request options, or any combination of # information that is available in the request or has already looked # up from some datastore. # # Create multiple instances of the following block, one for each # class. Differentiate between classes by setting # DHCP-SQL-Option-Context uniquely. # # - Place "subclass"-specific options (i.e. each member of a class) # in the dhcpreply table with "context = ". # - For class-level options common to every member of a class, # either: # - Duplicate the options for each member of the subclass. # or: # - Add "Fall-Through := Yes" to each members options to trigger # group lookups, which are disabled by default. # - Map each member of the class to a group in the dhcpgroup # table with context = ''; # - Create the corresponding class in the dhcpgroupreply table # with "context = ''". # # update control { # &DHCP-SQL-Option-Context := "class-vci-substring" # &DHCP-SQL-Option-Identifier := "%{substring %{request:DHCP-Vendor-Class-Identifier} 5 4}" # } # dhcp_sql.authorize }