Cisco Wireless LAN Controllers and DHCP Option 43

I recently had to install a Cisco Wireless LAN Controller (2112, if you’re interested), and had the usual fun and games with getting it to properly understand DHCP Option 43. For the uninitiated, option 43 is a vendor specific option, which, in the case of Cisco WLCs, is/are the manager IP address(es) of controllers that LWAPP access points should attempt to join when they boot up.

Different model APs require this option to be in different formats. For example, Aironet 1000 units require the option response to be type 0x66, and a comma-separated ASCII list of controller IP addresses, whereas Aironet 1130, 1200, 1230 and 1240 units require the response to be type 0xF1, followed by the length (number of addresses x four), then the hexadecimal representation of the controller IP address(es).

Cisco documentation exists for this, however their documentation for ISC’s dhcpd is incorrect. Unlike most corporate customers I run into, who run Microsoft DHCP server (for better or worse), this particular customer was running ISC’s dhcpd.

The first step is setting the option 43 type. I’m going to concentrate on the 1130, 1200, 1230 and 1240 units here, since this is the area where Cisco’s documentation is incorrect. I’m going to follow Cisco’s documentation here.

option space LWAPP;
option LWAPP.controller code 43 = string;

Then we have a vendor class, for the 1200 series units:

class "Cisco AP c1200" {
  match if option vendor class identifier = "Cisco AP c1200";
  option vendor class identifier "Cisco AP c1200";
  vendor option space LWAPP;
  option LWAPP.controller f1:04:c0:a8:f7:05;
}

Note the “f1:04” at the start of the string. This means type 0xF1, followed by four bytes of vendor specific data. The “c0:a8:f7:05” is the hexadecimal representation of the IP address 192.168.247.5. This results in dhcpd transmitting “2b 08 2b 06 f1 04 c0 a8 f7 05” for option 43.

Ok, let’s take a look at this string. The “2b” indicates this is a vendor encapsulated options field (type 43), and “08” means it’s eight bytes long. The next “2b” is where things start to go wrong. This is because the Cisco documentation told us to define LWAPP.controller as type 43 also, which is incorrect. The “06” indicates that six bytes follow for this sub-code, and then we have our “f1 04 c0 a8 f7 05” string verbatim. This causes the WLC to report an error parsing the option 43, saying that it cannot parse “2b 06 f1 04 c0 a8 f7 05”.

What we should have configured in dhcpd.conf is actually:

option space LWAPP;
option LWAPP.controller code 241 = string;

class "Cisco AP c1200" {
  match if option vendor class identifier = "Cisco AP c1200";
  option vendor class identifier "Cisco AP c1200";
  vendor option space LWAPP;
  option LWAPP.controller c0:a8:f7:05;
}

Note that we also dropped the “f1:04” from the hex string, since we are now correctly specifying LWAPP.controller as code 241 (0xF1), and dhcpd automatically populates the “04” for us, after counting the length of our hex string (four bytes = one IP address). This results in dhcpd sending “2b 06 f1 04 c0 a8 f7 05”.

Again we have our “2b”, indicating vendor encapsulated options, but this time the field is only six bytes long. Then we have “f1 04”, indicating our LWAPP.controller code, with four bytes of data – our controller IP address. This time around, the AP will correctly see the option 43 “payload” of just “f1 04 c0 a8 f7 05”, and correctly parse the sub-option 0xF1.

Of course, what this field really is (and this is more clearly detailed in Cisco’s instructions for configuring Microsoft DHCP server), is an array of IP addresses. You can eliminate the need to specify the addresses in hexadecimal by defining the LWAPP.controller as:

option LWAPP.controller code 241 = array of ip-address;

and then simply listing your controller IP addresses:

option LWAPP.controller 192.168.247.5, 192.168.247.6;

This would result in dhcp server sending “2b 0a f1 08 c0 a8 f7 05 c0 a8 f7 06”. Note the “f1 04” changed to “f1 08”, since the array length is now eight bytes (two IP addresses).

Why Cisco didn’t simply publish this, is beyond me. They’ve made it very confusing for users who don’t understand DHCP vendor specific information. I suspect the person who wrote the dhcpd section of the Cisco documentation didn’t fully understand how ISC dhcpd handles vendor specific options.

In any case, our configuration can be made somewhat clearer, and consistent with dhcpd’s documentation, as follows:

option space LWAPP;
option LWAPP.controller code 241 = array of ip-address;

class "LWAPP" {
  match option vendor-class-identifier;
}

subclass "LWAPP" "Cisco AP c1200" {
  vendor-option-space LWAPP;
  option LWAPP.controller 192.168.247.5;
}

For each additional type of AP you have to support, just add another subclass, using the appropriate vendor class identifier string.