Jul
23

The DHCP Information option (Option 82) is commonly used in metro or large enterprise deployments to provide additional information on “physical attachment” of the client. Option 82 is supposed to be used in distributed DHCP server/relay environment, where relays insert additional information to identify the client’s point of attachment.

As you know, DHCP relay is supposed to insert the “giaddr” field in the relayed DHCP packets, so that DHCP server may identify the pool to be used for the request. The choice of the pool is made based on the “giaddr” field or the incoming interface, if the “giaddr” is missing or zero . Option 82 serves as refinement to the request, allowing the DHCP server to select a “sub-range” in the pool. (Notice that by default Cisco IOS devices reject packets with zero “giaddr” and by default Cisco Catalyst switches use “giaddr” of zero when configured for DHCP snooping!)

The formatting of Option 82 field is as follows. The option starts with 0x52 (82 decimal) followed by the total option length. The option is structured in sub-options, formatted in the same way: . The list of options is terminated with option 0xFF so you can easily spot Option 82 in a packet dump.

<Option 82>  ::= 0x52 | LEN | <sub-option1> | <sub-option2> |.. | 0xFF |
<sub-option> ::= <option-id> <length> <contents>

RFC 3046 defines just a couple of sub-options, namely the “remote-id” (option ID 0x2) and the “circuit-id” (ID 0x01). Those two are supposed to identify the remote device and the port where the DHCP request was received. However, many vendors prefer using their own extensions to Option 82, based on its flexible format. This freedom of choice leads to some serious consequences with respect to IOS devices configuration. We are now going to discuss this a bit later. For now, keep in mind that IOS devices use sub-option 0x6 instead of 0x1 for circuit identification (at least the more recent IOS releases). The formatting of the sub-options is also vendor and software version dependent!

In Cisco IOS devices, you configure information-option based address allocation using the concept of DHCP class. A given class specifies the range of Option 82 values and could be associated with a range of addresses in DHCP pool. Before you can use classes, make sure the command ip dhcp use class is enabled in router’s configuration (the default). After this, you may create a class as follows:

ip dhcp class TEST
relay agent information
relay-information hex 020c01020304*

Notice the use of “*” globbin pattern to match any string of characters after the initial substriting. This type of formatting specifies the value of DHCP Option 82 in “raw” format – that is, no structure is specified in the option. The value used in the class is everything that follows the initial "0x52 " tuple in Option 82 - that is, the list of all sub-options, including their initial ID/Length tuples. The terminating option 0xFF is not included in the relay-information field. Due to the flexibility of Option 82 formats, Cisco IOS only allows you using the “raw” formatting, without any referencing to the sub-options and their values. In addition to the globbing character “*” you may also use inverse wildcard mask as follows:

relay-information hex  bitmask 0000000FF

where the bitmask follows the same syntax as an access-list wildcard, with “1” meaning “don’t care”. Notice that the relay-information value is formatted in hex and should contain even number of character. The bitmask should match the relay-information length.

Next, after you have the class configured, you may associate it with a DHCP pool. Remember that the pool address range should match the “giaddr” IP address found in the relayed packet:

ip dhcp pool POOL
network 204.12.1.0 255.255.255.0
class TEST
address range 204.12.1.100 204.12.1.100

Notice how the range is assigned to the class associated with the DHCP pool. Now the question that people usually ask is: “If IOS uses raw formatting for Option 82, how do I find the value used by the remote relay?”. Cisco documentation refers you back to the “vendors” specifications for the use of Option 82. What if you just configured a server and a relay and want to learn the value of DHCP Option 82 used?

1) Make sure remote device is configured for insertion of Option 82. For an IOS router, you may want to have a configuration similar to the following:

ip dhcp relay information option
!
interface Fa 0/0
ip helper-address 10.0.0.1
ip dhcp relay information option subscriber-id TEST

The above configuration sets the value of the subscriber-ID (even though it’s NOT sub-option 0x2, but rather sub-option 0x6). Notice that by default, the information option is not being inserted by IOS routers. Furthermore, the syntax is different for IOS switches and may vary from model to model. By default, when you enable DHCP snooping in a 3550/3560 switch, the switch will be inserting the information option but will set “giaddr” to zero. To handle this in an IOS router, use the command ip dhcp relay information trust-all to accept packets with zero “giaddr”.

2) Configure a DHCP pool matching the remote “giaddr” IP address value. Create a DHCP class with a relay-information value that should never be met in real life. For example set the value to “00000000*” which should never match any sub-option. Associate this class with the pool and configure a sub-range as usual.

3) Enable the following debug in the server: debug ip dhcp server class which tracks the class-based allocation. When an incoming packet contains a DHCP Option 82 that does not match any class, the output similar to the following will appear:

DHCPD: Class 'TEST' matched by default
DHCPD: Searching for a match to 'relay-information
020c020a0000cc0c010200000000060454455354' in class TEST

revealing the actual value of Option 82 in the packet. In the output above, there ate two sub-options: 0x2 with the length of 0xc and 0x6 with the length of 0x4. Using this debugging output you may quickly learn the value of Option 82 used by the remote relay, without referring to any low-level debugging commands.

The above posted quickly summarizes all you probably need to know about Option 82 and its relation to the CCIE R&S exam.

May
03

A question on GroupStudy gave me an idea for the short post dedicated to explaining the use of DHCP “import all” command. The command first appeared in IOS 12.2T. It allows importing certain DHCP information learned from some external source, such as another DHCP server. This is helpful in reducing the amount of configuration needed in large hub-and-spoke networks, where spokes use centralized servers (e.g. WINS, DNS, TFTP). Instead of configuring the repetitive settings in every spoke router, you may import them by requesting an IP address for the router via DHCP. More than that, any change in central configuration could be easily imported in the remote routers, using DHCP address refresh. Here is how it works:

1) The router requests an IP address on its WAN interface via DHCP. In addition to the IP/subnet information, the router also learns other DHCP information, such as various DHCP options (DNS, WIN, TFTP IP addresses). This is store with the local DHCP client configuration.
2) The is a local pool configured in the router, with the subnet corresponding to the local Ethernet interface (say office network). This pool is configured with the statement “import all”.
3) By the virtue of “import all” statement and the default “origin dhcp” setting, the local pool imports the information learned by the router’s DHCP client. The imported information does not preempt the local subnet and mask, but instead add missing information.
4) Every time the DHCP lease expires, the router will re-request it, thus re-learning all other information as well.

As an alternative to using the DHCP it is possible to use IPCP for information import, if the WAN link uses PPP protocol (e.g. PPPoE). You simply need the statement “ip address negotiated” on the PPP link plus configured “origin ipcp” under the DHCP pool. Notice that the amount of IPCP options is much smaller than that of DHCP. However, you may still send WINS and DNS servers IP addresses, and even the netmask, using the command “ppp ipcp mask”. See the post The myster of “PPP IPCP mask request command” for more information on this command.

Here is a sample configuration.

R1 is the DHCP client to R3. The server has a DCHP pool for subnet 10.0.0.0/24 configured, with TFTP, DNS and WINS servers set. All servers belong to the Ethernet segment connected to R3. R1 imports those settings from R3. Notice the use of the Dialer interface in R1 - you cannot configure "ip address dhcp" on the physical interface, as this feature was intended for use with PPPoE/PPPoA interfaces. Also, pay attention to the "ip unnumbered" command on R3's PPP interface. It is important to have this command, so that incoming DHCP REQ packets are matched against R3's DHCP pool.

R1:
interface Serial0/1
no ip address
encapsulation ppp
dialer in-band
dialer pool-member 1
!
interface Dialer1
ip address dhcp
dialer pool 1
!
ip dhcp pool LOCAL
import all
network 20.0.0.0 255.255.255.0
default-router 20.0.0.1
!
interface FastEthernet0/0
ip address 20.0.0.1 255.255.255.0
R3:
ip dhcp pool POOL
network 10.0.0.0 255.255.255.0
dns-server 10.0.0.100 10.0.0.200
netbios-name-server 10.0.0.100
option 150 ip 10.0.0.150
default-router 10.0.0.3
!
interface FastEthernet0/0
ip address 10.0.0.3 255.255.255.0
!
interface Serial1/2
ip unnumbered FastEthernet0/0
encapsulation ppp
clock rate 128000

And now some quick verifications:

R1#show ip dhcp pool 

Pool LOCAL :
Utilization mark (high/low) : 100 / 0
Subnet size (first/next) : 0 / 0
Total addresses : 254
Leased addresses : 0
Pending event : none
1 subnet is currently in the pool :
Current index IP address range Leased addresses
20.0.0.1 20.0.0.1 - 20.0.0.254 0

R1#show ip dhcp import

Address Pool Name: LOCAL
Domain Name Server(s): 10.0.0.100 10.0.0.200
NetBIOS Name Server(s): 10.0.0.100
TFTP Server Address Option: 10.0.0.150

R3#show ip dhcp binding
Bindings from all pools not associated with VRF:
IP address Client-ID/ Lease expiration Type
Hardware address/
User name
10.0.0.2 0063.6973.636f.2d30. May 04 2009 10:21 AM Automatic
3030.642e.6564.6338.
2e34.6636.302d.4469.
31

And last, but not least. It is possible to import the DHCP pool information from a RADIUS server, which sounds pretty attractive. However, we do not provide an example in this post. Maybe next time :)

Jul
06

If you ever used IPCP for address allocation with PPP ("ip address negotiated" on client side and "peer default ip address" on server side) you may have noticed that the mask assigned to a client is always /32. It does not matter what mask a server uses on it's side of the connection, just PPP is designed to operate this way.

However, many have noticed two strange commands "ppp ipcp mask request" and "ppp ipcp mask X.X.X.X" under PPP interface configuration mode. If IPCP assigned address never uses a custom mask, what would the purpose of those commands be? The answer is simple - to configure on-demand address pools in a client. That is, a client may request a DHCP pool parameters from server using IPCP - for example request a subnet and a mask. The client may then further use this information and allocate IP addresses to it's subordinates. Here is a configuration to verify this feature. Consider that R1 connects to R3 over a point-to-point link:

R1:
ip dhcp pool LOCAL
import all
origin ipcp
!
! Link to R3
!
interface Serial0/1
ip address pool LOCAL
encapsulation ppp
ppp ipcp mask request

R3:
!
! Link to R1
!
interface Serial1/2
ip address 172.16.13.3 255.255.255.0
encapsulation ppp
peer default ip address pool POOL
clock rate 128000
ppp ipcp mask 255.255.255.0
!
ip local pool POOL 172.16.100.1 172.16.100.254

Using the "debug ppp negotiation" command on R1 (the client) and R3 (the server) you may see the mask being requested and passed down to the client. Debug output from R1:

Se0/1 IPCP: I CONFREQ [REQsent] id 1 len 10
Se0/1 IPCP: Address 172.16.13.3 (0x0306AC100D03)
Se0/1 IPCP: O CONFACK [REQsent] id 1 len 10
Se0/1 IPCP: Address 172.16.13.3 (0x0306AC100D03)
Se0/1 CDPCP: Redirect packet to Se0/1
Se0/1 CDPCP: I CONFREQ [REQsent] id 1 len 4
Se0/1 CDPCP: O CONFACK [REQsent] id 1 len 4
Se0/1 IPCP: I CONFNAK [ACKsent] id 1 len 20
Se0/1 IPCP: VSO OUI 0x00000C kind 1 (0x000A00000C01FFFFFF00)
Se0/1 IPCP: Address 172.16.100.3 (0x0306AC106403)
Se0/1 IPCP: O CONFREQ [ACKsent] id 2 len 20
Se0/1 IPCP: VSO OUI 0x00000C kind 1 (0x000A00000C01FFFFFF00)
Se0/1 IPCP: Address 172.16.100.3 (0x0306AC106403)
Se0/1 CDPCP: I CONFACK [ACKsent] id 1 len 4
Se0/1 CDPCP: State is Open
Se0/1 IPCP: I CONFACK [ACKsent] id 2 len 20
Se0/1 IPCP: VSO OUI 0x00000C kind 1 (0x000A00000C01FFFFFF00)
Se0/1 IPCP: Address 172.16.100.3 (0x0306AC106403)
Se0/1 IPCP: State is Open
Se0/1 IPCP: Subnet: address 172.16.100.3 mask 255.255.255.0

Debug output from R3:

Se1/2 IPCP: O CONFREQ [Closed] id 1 len 10
Se1/2 IPCP: Address 172.16.13.3 (0x0306AC100D03)
Se1/2 CDPCP: O CONFREQ [Closed] id 1 len 4
Se1/2 PPP: Process pending ncp packets
Se1/2 IPCP: I CONFREQ [REQsent] id 1 len 20
Se1/2 IPCP: VSO OUI 0x00000C kind 1 (0x000A00000C0100000000)
Se1/2 IPCP: Address 172.16.100.3 (0x0306AC106403)
Se1/2 IPCP: Use our explicit subbnet mask 255.255.255.0
Se1/2 IPCP: O CONFNAK [REQsent] id 1 len 14
Se1/2 IPCP: VSO OUI 0x00000C kind 1 (0x000A00000C01FFFFFF00)
Se1/2 CDPCP: I CONFREQ [REQsent] id 1 len 4
Se1/2 CDPCP: O CONFACK [REQsent] id 1 len 4
Se1/2 CDPCP: I CONFACK [ACKsent] id 1 len 4
Se1/2 CDPCP: State is Open
Se1/2 IPCP: I CONFACK [REQsent] id 1 len 10
Se1/2 IPCP: Address 172.16.13.3 (0x0306AC100D03)
Se1/2 IPCP: I CONFREQ [ACKrcvd] id 2 len 20
Se1/2 IPCP: VSO OUI 0x00000C kind 1 (0x000A00000C01FFFFFF00)
Se1/2 IPCP: Address 172.16.100.3 (0x0306AC106403)
Se1/2 IPCP: Use our explicit subbnet mask 255.255.255.0
Se1/2 IPCP: O CONFACK [ACKrcvd] id 2 len 20
Se1/2 IPCP: VSO OUI 0x00000C kind 1 (0x000A00000C01FFFFFF00)
Se1/2 IPCP: Address 172.16.100.3 (0x0306AC106403)

Now this is what you get when you configure "ip address negotiated" on R1:

R1#sh ip interface serial 0/1
Serial0/1 is up, line protocol is up
Internet address is 172.16.100.5/32
Broadcast address is 255.255.255.255
Address determined by IPCP
Peer address is 172.16.13.3

And this is what shows up when you use local DHCP address pool for autoconfiguration (note the subnet mask):

R1#sh ip interface serial 0/1
Serial0/1 is up, line protocol is up
Internet address is 172.16.100.4/24
Broadcast address is 255.255.255.255
Address determined by setup command
Peer address is 172.16.13.3

However, the funniest part is that R1 serial interface IP address is actually not allocated from the local (on-demand) DHCP pool! Observing the debug output you can see that R1 uses the IP address sent from R3, not allocated from the local DHCP pool. Then again, the local pool DHCP still has the requested subnet:

R1#sh ip dhcp pool 

Pool LOCAL :
Utilization mark (high/low) : 100 / 0
Subnet size (first/next) : 0 / 0
Total addresses : 254
Leased addresses : 0
Pending event : none
1 subnet is currently in the pool :
Current index IP address range Leased addresses
172.16.100.1 172.16.100.1 - 172.16.100.254 0

R1#sh ip dhcp binding
Bindings from all pools not associated with VRF:
IP address Client-ID/ Lease expiration Type
Hardware address/
User name
R1#

You can see the following on R3:

R3#sh ip local pool POOL
Pool Begin End Free In use
POOL 172.16.100.1 172.16.100.254 253 1
...
172.16.100.1 Se1/2
172.16.100.2 Se1/2
172.16.100.3 Se1/2
172.16.100.4 Se1/2
Inuse addresses:
172.16.100.4 Se1/2

This is what so funny about Cisco IOS - you can never be sure the feature works in a most logical way you may suppose it to work. You can play with this example further, for example changing IP address allocation on R3 to local DHCP Pools or a static IP - there is always something you can experiment with!

Further reading:

Configuring the DHCP Server On-Demand Address Pool Manager

Subscribe to INE Blog Updates

New Blog Posts!