Thursday, May 16, 2013

CCIE Voice Tactics: Dealing with IOS DHCP

To complement the CCIE-V Strategy Series I am going through the process of parsing my IE voice notes and pulling out the more interesting bits. As with the other series hosted on this blog, I base my topic choices on perceived (subjective) interest, requests via comments, and the common questions I see on various forums.

For this installment, I am going to walk through some of the tactics around DHCP.


I am not going into DHCP on CUCM because getting DHCP running on CUCM is fairly simple and straightforward. Generally speaking, getting DHCP running on IOS is simple too. Though, there are a couple of scenarios that are not as mundane and worth talking about.

Vanilla DHCP on IOS

The most basic question you can be asked is to allocate a range of IP addresses to be used by a specific site's IP phones. For instance:
For Site B, ensure that phones get an IP address in the range of and

You will also be given information on how to allocate TFTP to DHCP scopes. This may be directly provided in the question or may be buried somewhere else in the exam guide. This is why we do a read through and take note of the primary and secondary TFTP servers. Anyway, continuing with the above example we could provide the following config:

ip dhcp exclude
ip dhcp exclude
ip dhcp pool PHONES
 network /24
 default    << assuming this is the SVI address
 option 150 ip   << UCM servers

Wow, that was exciting. Let's move on, shall we?

Static DHCP on IOS

Taking it up a notch, let's say you had a question like the following:
For Site B, ensure that phones get an IP address in the range of and and that Site B Phone 2 always gets assigned the address
The following config will address the question:

ip dhcp exclude
ip dhcp exclude
ip dhcp pool PHONES
 network /24
 default    << assuming this is the SVI address
 option 150 ip   << UCM servers
ip dhcp pool PHONE2
 host /24
 client-id 01DE.ADBE.EF00.01
 default    << assuming this is the SVI address
 option 150 ip   << UCM servers

The interesting bits:

  • When you have to statically assign an IP address to a device then you should exclude it from the address ranges available to any other DHCP pool
  • You create a custom pool for the static reservation
  • You use "host" and not "network" when assigning the address
  • You identify the MAC address for static assignment by using the "client-identifier" command under the DHCP pool. Oh, and you stick a "01" in front of the MAC address AND you have to use dotted hex format

Origin Files and DHCP on IOS

Building on the static DHCP requirement, it is possible that you are asked to assign specific addresses while being limited to creating one DHCP pool. The methodology here is a little more involved because you have to create a properly formatted text file that stores the client address assignments. 

The sample question:
For Site B, ensure that phones get an IP address in the range of and Ensure that Site B Phone 2 always gets assigned the address and that Site B Phone 1 always gets assigned the address

So, tackling this is a multi-step process.

Step 1: Get the MACs

My approach to the lab meant that I always had a notepad file opened where I initially write out configs for my devices. I have a separate notepad for each device. So, the first step is to create a section for DHCP in that notepad and then take note of the MAC addresses for the phones.  

!---------> dhcp
ieswitch01#sh cdp nei | i SEP
SEP001E4A924D19  Fas 0/12          145             H P M  IP Phone  Port 1
SEP0017958168D3  Fas 0/11          124             H P M  IP Phone  Port 1


Step 2: Create Origin File

You can memorize the origin file format or you can create a copy and then manipulate it later.  I prefer the latter. To create the origin file you have to essentially tell the IOS DHCP service that there is a local database file in flash and then force the service to write to that file (thus, creating a properly formatted file).

The example: 

SiteB-RTR(config)#ip dhcp database flash:static.txt
SiteB-RTR(config)#ip dhcp pool PHONES
SiteB-RTR(config)#no serv dhcp
SiteB-RTR(dhcp-config)#do more static.txt
*time* Jan 18 2013 06:18 PM
*version* 4
!IP address     Type  Hardware address   Lease expiration       VRF

!IP address      Type     Hardware address  Interface-name

!IP address     Interface-name  Lease expiration      Server IP address  Hardware address  Vrf

Step 3: Compose TCLSH Commands to Edit Origin

After you have the proper syntax for the file then you need to add client information to the file. You also need to get the file on the IOS device. You have a few options here:
  1. You could create a text file and upload it to one of the UCM TFTP servers. From there you can TFTP it to the IOS device
  2. You could upload a file to UCM as noted above. Instead of copying the file down to the IOS device's flash, you could actually tell the DHCP pool to use an origin file directly from the TFTP server
  3. You could use tclsh to edit the origin file "on box"

I go with option 3. It is by far the fastest approach. Copy the contents of the static.txt file into notepad and then edit the notepad to include the necessary TCL commands. An example config looks like this (in notepad):

set fh [open "flash:static.txt" w+]
puts $fh {*time* Jan 18 2013 06:18 PM
*version* 4
!IP address     Type  Hardware address   Lease expiration       VRF /24     id     0100.1795.8168.D3     Infinite /24     id     0100.1E4A.924D.19     Infinite
!IP address      Type     Hardware address  Interface-name

!IP address     Interface-name  Lease expiration      Server IP address  Hardware address  Vrf

close $fh

So, what the hell is going on here? We are basically stubbing out the syntax needed to leverage TCL shell (tclsh) in IOS to open a file and re-write the file contents. The set fh [ open ... ] line is basically opening the file flash:static.txt for writing and setting a variable called "fh" to hold the file handle reference. 

The puts $fh { ...stuf... } is using the put string method (puts) to dump a multi-line string into the file we have referenced with the $fh variable. The close $fh at the end will cleanly close the file. Yes, you can get away with not doing a close but my OCD won't let me do that. It is just a bad practice.

Now, getting to the meat of our goal here. Notice that we have added two static entries. You want to follow the conventions shown above. Items that are worth noting:

  • You want to specify IP address and mask and you should have a space between both
  • You want to set the record type to "id"
  • You can use spaces or tabs between fields, I used tabs
Note: A reader posted that they had issues with multiple spaces between fields. So, use tabs or test with using a single white space between fields.
  • You have to prefix "01" to the client mac address and you have to use the hex-dotted format for the Hardware address field
  • Set the lease expiration to "Infinite"

Step 4: Apply the Config

The way I do this is as follows:
  • Console to the IOS device
  • Get in enable mode (router#)
  • Type in command: tclsh , this will get you into the TCL shell interpreter
  • Copy/paste the line set fh [ open "flash:static.txt" w+] from notepad into the terminal app
  • Then copy/paste the entire puts command and the close $fh command from notepad into the terminal app
  • Type in command: tclq to exit the TCL shell 
It is a good idea to take a quick peak at your static.txt file using the more command: more flash:static.txt. Make sure your edits are present.

Step 5: Wrap it Up

What we need to do is put the DHCP service back on line, remove the configs we used to create our file template, and finish configuring the DHCP pool. The following is a transcript of how I do the wrap up:

SiteB-RTR#conf t
SiteB-RTR(config)#no ip dhcp database flash:static.txt
SiteB-RTR(config)#ip dhcp pool PHONES
SiteB-RTR(dhcp-config)#origin file flash:static.txt
SiteB-RTR(dhcp-config)#option 150 ip
SiteB-RTR(config)#serv dhcp

We should now have a working DHCP solution. To verify use the show ip dhcp bind command to view the active bindings. For example:

SiteB-RTR#sh ip dhcp bind
Bindings from all pools not associated with VRF:
IP address          Client-ID/              Lease expiration        Type
                    Hardware address/
                    User name     0100.1795.8168.d3       Infinite                Static     0100.1e4a.924d.19       Infinite                Static

Thanks for reading. If you have time, post a comment!


  1. Hello Will

    I achieve the task using option 1 and 2,but the tclsh option it's great .

    thanks for share!!!

  2. Hello William,

    With the Create Origin File method did you still use the dhcp excluded-address command?

    1. Robert,

      It depends. If there are other phones in the network that could possibly grab the IP addresses then you would want to use exclusions. If you were creating a static assignment for all possible clients on the subnet then exclusions are unnecessary.


      -Bill (@ucguerrilla)

  3. hi,

    i really admire ur blogs,
    just one thought what if we do dhcp in the below given way:
    1) create excluded adds
    2) create database file (ip dhcp database sticky.txt)
    3) create simple pool
    4) open the ports of the phone one by one in the order u want them to get the IPs (i.e. aaaa.aaaa.aaaa first it will get IP .51 bbbb.bbbb.bbbb second it will get IP .52)
    5) wait for the dhcp to write the bindings to the file.
    6) no ip dhcp database flash:sticky.txt
    7) ip dhcp pool pool1
    origin file flash:sticky.txt
    and done!
    what do u think

    1. Thanks for the complement and thanks for reading. The process you describe should work. IIRC, the records will be written to the sticky.txt file using the required format. I have heard others use this method successfully.


      -Bill (@ucguerrilla)

  4. Bill, thank you for a great TCL example! Works like a charm and saves lots of time.

  5. Hi Bill, just a quick follow up.
    I'm not sure if this is a bug, but if in static pool .txt file I'm using multiple spaces instead of tabs to separate address/type/lease, phones aren't getting IP's
    During debug I'm getting the following message
    Jul 11 03:54:24.016: DHCPD: there is no address pool for
    All other configuration is identical so I'd recommend not to use spaces. With tabs everything work perfect.

    1. I keep getting "DHCPD: could not parse hardware address " tried spaces , tabs, lowercase , uppercase, using tftp or tcl is this a bug ?
      (IOS Version 12.4(24)T2)

  6. I have been using this in some of my practice lately, and it is working great. I had a problem still with my phones registering though, and just figured out that it was my WAN QOS chocking it out somehow, where the tftp file wouldn't download... Have to double check those configs now!

  7. Hey Bill,

    Really cool site. Tons of excellent information on here. I really appreciate you taking the time to post this stuff.

    I know next to nothing about TCL scripts but I was in pursuit of a quicker way to do static dhcp using a single pool if I was faced with a question like that on the IE Voice exam and came up a solution using TCL as well. When I found your post and saw you were also a fan of this method I figured I would share mine in case anyone found it useful. It is basically the same as yours except I just use the "puts" TCL command to create the file and since I know very little about TCL then it is easier for me to remember. I too script it out in notepad first and then paste the info in so this is what I put in notepad... (Note: This assumes there is not a file on the flash already called static.txt. If there is for some reason then I'll delete it first and start fresh).

    puts [open flash:static.txt w+] {
    *time* Dec 03 2013 9:57 PM /24 id 0100.2414.2E4F.03 Infinite /24 id 0100.2414.2E75.80 Infinite

    Then I go over to my router and type "tclsh" and then paste the above in and type "exit". I found that if I try to paste everything in including the "tclsh" in the beginning then not everything takes so that is why I type that in manually and then just paste the contents.

    Then I build the pool to reference the file...

    config t
    ip dhcp pool STATIC
    option 150 ip
    origin file static.txt

    From start to finish this is what it looks like for me...

    BR2#delete flash:static.txt
    Delete filename [static.txt]?
    Delete flash:/static.txt? [confirm]

    BR2#more flash:static.txt
    %Error opening flash:static.txt (File not found)

    BR2(tcl)#puts [open flash:static.txt w+] {
    +>*time* Dec 03 2013 9:57 PM
    +> /24 id 0100.2414.2E4F.03 Infinite
    +> /24 id 0100.2414.2E75.80 Infinite


    BR2#more flash:static.txt
    *time* Dec 03 2013 9:57 PM /24 id 0100.2414.2E4F.03 Infinite /24 id 0100.2414.2E75.80 Infinite

    BR2#config t
    Enter configuration commands, one per line. End with CNTL/Z.
    BR2(config)#ip dhcp pool STATIC
    BR2(dhcp-config)#option 150 ip
    BR2(dhcp-config)#origin file static.txt

    Again I know very little about TCL but this method worked for me and only required me to remember one line of code as far as the TCL stuff was concerned.

    I like your suggestion about using the ip dhcp database command to remember the syntax of the file. I wasn't familiar with that previously and had spent some time just trying to memorize the format. Now I have something to fall back on if needed.

    Thanks again for the great content. Take care.

  8. Thanks for the great feedback!


  9. Hey Bill
    Great post...

    I have tried this method. But when I use "show ip dhcp binding" I am unable to see ip address assigned to the phones.

    How can I troubleshoot this?

    1. That could indicate a failure to restart the dhcp service or a failure to close the file properly. I'd use "more" to look at the file and make sure dhcp service is started. You may also want to check the records (lines) in the file to make sure it is properly formatted, that the time and version lines are provided (they are required), make sure you used an infinite lease expiration, etc.