C++17 library for CAPWAP protocol (Control and Provisioning of Wireless Access Points) packet definitions according to RFC 5415 and RFC 5416.
This repository is designed to be included as a git submodule in other projects.
src/
├── *.h, *.cpp # CAPWAP message types (DiscoveryRequest, JoinRequest, etc.)
└── elements/ # CAPWAP message elements
├── *.h, *.cpp # Generic elements (ACDescriptor, WTPDescriptor, etc.)
└── IEEE80211/ # IEEE 802.11 binding elements (RFC 5416)
tests/
├── unit_tests/ # Unit tests
└── benchmarks/ # Performance benchmarks
docs/
├── rfc5415.txt # CAPWAP Protocol Specification
└── rfc5416.txt # CAPWAP Binding for IEEE 802.11
git submodule add <repository-url> path/to/vi-capwap-protocol
git submodule update --init --recursiveThen include the necessary headers in your project:
#include "vi-capwap-protocol/src/DiscoveryRequest.h"
#include "vi-capwap-protocol/src/elements/ACDescriptor.h"Important: This library is designed for zero-copy operation. CAPWAP messages and elements do not take ownership of the data passed to them.
When passing data via nonstd::span<const uint8_t> to writable arrays (e.g., WritableRateSetArray, WritableStationArray), the caller must ensure that the referenced data remains valid until Serialize() is called.
std::vector<uint8_t> rate_set_data = { 0x82, 0x84, 0x8B, 0x96 };
WritableRateSetArray rate_sets;
rate_sets.Add(1, rate_set_data); // span references rate_set_data
rate_sets.Serialize(&raw_data); // rate_set_data must still be valid hereWritableRateSetArray rate_sets;
{
std::vector<uint8_t> rate_set_data = { 0x82, 0x84, 0x8B, 0x96 };
rate_sets.Add(1, rate_set_data);
} // rate_set_data destroyed - span now points to invalid memory!
rate_sets.Serialize(&raw_data); // Undefined behaviorRequired for standalone builds (unit tests and benchmarks). When used as a git submodule, the parent project provides its own logging backend.
- Debian/Ubuntu:
sudo apt install libspdlog-dev
- Debian/Ubuntu:
sudo apt install libfmt-dev
# Build and run unit tests
make build_tests
./output/tests/unit_tests/vi-capwap-tests
# Build and run benchmarks
make build_benchmarks
./output/tests/benchmarks/vi-capwap-benchmarksThe library builds for both little-endian (x86, ARM) and big-endian (MIPS) targets.
The byte order is detected from the compiler via __BYTE_ORDER__. If a toolchain
does not define it, the build fails with an explicit error rather than guessing —
override it manually in that case:
-DVI_CAPWAP_BIG_ENDIAN=1 # or 0- Multi-byte protocol fields must use
NetworkU16,NetworkU32orNetworkS16(src/Helpers.h). They are built and read byte by byte, so they carry no byte order assumption. Never put a rawuint16_t/uint32_tin a packed structure. - Protocol constants stored raw in packed structures (message and element types,
result codes) must be wrapped in
ToNetworkOrder16()/ToNetworkOrder32(), which spell them in the target's byte order at compile time. - Comparing such a constant needs no conversion: equality does not depend on the
representation. Only ordering comparisons (
<,>, ranges) requireToHostOrder*, because byte swapping does not preserve order. - Bit fields in packed structures are allocated from the most significant bit on
big-endian targets. Every such structure declares both orders behind
#if VI_CAPWAP_BIG_ENDIAN, mirrored within each octet, and constructor member init lists follow the same split. A bit field must never cross an octet boundary. - IPv4 address fields are raw
uint32_tholding values in network byte order, as returned byinet_addr()/inet_pton(). They are stored as-is and need no conversion on either target.
The unit tests compare serialized output against literal wire bytes, so running the suite on a big-endian target verifies the byte order handling end to end.
sudo apt install g++-mips-linux-gnu qemu-user-static
make run_tests_be # cross build for MIPS and run under qemu
make clean_tests_beCross targets have no system spdlog, so run_tests_be compiles logging out
(LOG_LEVEL=LOG_LEVEL_NONE). The compiler, sysroot and emulator can be overridden
through BE_CXX, BE_SYSROOT and BE_QEMU.
# Check code formatting
make check_format
# Apply code formatting
make apply_format
# Static analysis
make code_checkWhen constructing CAPWAP messages with radio information, the following constraints must be satisfied:
-
Maximum radios constraint:
max_radios >= radios_in_use- The maximum number of radios supported by WTP must be greater than or equal to the number of radios currently in use
-
Radio info array size:
radios_in_use <= wtp_radio_info.size()- The
wtp_radio_infoarray must contain at leastradios_in_useelements
- The
These requirements are enforced by runtime assertions in the library.
RFC 5415/5416 specify that Radio ID must be in the range 1-31. This implementation extends the valid range to 0-31 to support special cases or vendor-specific requirements.
Standard Range (RFC): 1-31 Implementation Range: 0-31
This extension is intentional and does not affect interoperability with RFC-compliant implementations, as Radio ID 0 is simply an additional option that can be used or avoided as needed.
RFC 5415 assigns Result Codes 0-22. This implementation adds ten codes for vendor-defined conditions, placed well above the standard block so they cannot collide with future assignments by the RFC.
Standard Range (RFC): 0-22
Vendor-Specific Range: 0xF000-0xF009 (ResultCode::VendorSpecific_1 … VendorSpecific_10)
WritableResultCode result{ ResultCode::Type::VendorSpecific_1 };ResultCode::Validate() accepts both ranges and rejects everything else, so a peer that does
not know these codes simply fails to parse the element rather than misinterpreting it.
These codes are meaningful only between endpoints that agree on them. An RFC-compliant AC or WTP will reject them, so they must not be used where interoperability with third-party implementations is required.
This library implements IEEE 802.11 binding for CAPWAP (RFC 5416) with the following coverage:
✓ Fully Implemented:
- Discovery Request/Response (Section 5.1, 5.2)
- Join Request/Response (Section 5.5, 5.6)
- Configuration Status Request/Response (Section 5.7, 5.8)
- Configuration Update Request/Response (Section 5.9)
- Change State Event Request/Response (Section 5.11)
- WTP Event Request/Response (Section 5.12)
- WLAN Configuration Request/Response (Section 3.1, 3.2)
Not Implemented (Optional):
- Primary Discovery Request/Response (Section 5.3, 5.4) - optional per RFC 5415
- Station Configuration Request/Response (Section 5.10) - optional, but individual elements are implemented
All 25 IEEE 802.11-specific message elements from RFC 5416 Section 6 are fully implemented:
- Add/Delete/Update WLAN management
- Radio configuration (Antenna, Direct Sequence, OFDM, TX Power, etc.)
- Station management (Station, Session Key, QoS Profile)
- Information Elements and Statistics
- All elements have comprehensive unit test coverage
This implementation provides complete functionality for managing WTP radios and WLANs in production environments.
This section describes how CAPWAP protocol elements are organized by their structure and usage patterns.
Elements are grouped based on their structural characteristics and how they appear in messages.
Single-occurrence elements containing multiple fields, where the last field is an array of nested sub-elements.
- 4.6.1. AC Descriptor (src/elements/ACDescriptor.h)
- 4.6.40. WTP Board Data (src/elements/WTPBoardData.h)
- 4.6.41. WTP Descriptor (src/elements/WTPDescriptor.h)
Single-occurrence elements consisting exclusively of an array of uniform fields.
- 4.6.2. AC IPv4 List (src/elements/ACIPv4List.h)
Single-occurrence elements whose body consists entirely of one dynamically-sized field.
- 4.6.4. AC Name (src/elements/ACName.h)
- 4.6.30. Location Data (src/elements/LocationData.h)
- 4.6.32. MTU Discovery Padding (src/elements/MTUDiscoveryPadding.h)
- 4.6.45. WTP Name (src/elements/WTPName.h)
Elements that can appear multiple times in a message. Consist of static fields and end with a variable-length field.
- 4.6.5. AC Name with Priority (src/elements/ACNameWithPriority.h)
- 4.6.17. Decryption Error Report (src/elements/DecryptionErrorReport.h)
- 4.6.20. Delete Station (src/elements/DeleteStation.h)
- 4.6.22. Duplicate IPv4 Address (src/elements/DuplicateIPv4Address.h)
- 4.6.36. Returned Message Element (src/elements/ReturnedMessageElement.h)
- 4.6.39. Vendor Specific Payload (src/elements/VendorSpecificPayload.h)
Single-occurrence elements with strictly fixed size.
- 4.6.6. AC Timestamp (src/elements/ACTimestamp.h)
- 4.6.13. CAPWAP Timers (src/elements/CAPWAPTimers.h)
- 4.6.14. CAPWAP Transport Protocol (src/elements/CapwapTransportProtocol.h)
- 4.6.21. Discovery Type (src/elements/DiscoveryType.h)
- 4.6.24. Idle Timeout (src/elements/IdleTimeout.h)
- 4.6.25. ECN Support (src/elements/ECNSupport.h)
- 4.6.28. Image Information (src/elements/ImageInformation.h)
- 4.6.29. Initiate Download (src/elements/InitiateDownload.h)
- 4.6.31. Maximum Message Length (src/elements/MaximumMessageLength.h)
- 4.6.35. Result Code (src/elements/ResultCode.h)
- 4.6.37. Session ID (src/elements/SessionId.h)
- 4.6.38. Statistics Timer (src/elements/StatisticsTimer.h)
- 4.6.42. WTP Fallback (src/elements/WTPFallback.h)
- 4.6.43. WTP Frame Tunnel Mode (src/elements/WTPFrameTunnelMode.h)
- 4.6.44. WTP MAC Type (src/elements/WTPMACType.h)
- 4.6.47. WTP Reboot Statistics (src/elements/WTPRebootStatistics.h)
- 4.6.48. WTP Static IP Address Information (src/elements/WTPStaticIPAddressInformation.h)
Single-occurrence elements in a message. Have several static fields and end with a variable-length field.
- 4.6.7. Add MAC ACL Entry (src/elements/AddMacAclEntry.h)
- 4.6.19. Delete MAC ACL Entry (src/elements/DeleteMacAclEntry.h)
- 4.6.26. Image Data (src/elements/ImageData.h)
- 4.6.27. Image Identifier (src/elements/ImageIdentifier.h)
Strictly fixed-size elements that can appear multiple times in a message.
- 4.6.9. CAPWAP Control IPv4 Address (src/elements/CAPWAPControlIPv4Address.h)
- 4.6.11. CAPWAP Local IPv4 Address (src/elements/CAPWAPLocalIPv4Address.h)
- 4.6.18. Decryption Error Report Period (src/elements/DecryptionErrorReportPeriod.h)
- 4.6.33. Radio Administrative State (src/elements/RadioAdministrativeState.h)
- 4.6.34. Radio Operational State (src/elements/RadioOperationalState.h)
- 4.6.46. WTP Radio Statistics (src/elements/WTPRadioStatistics.h)
Elements specific to IEEE 802.11 wireless binding, grouped by structure.
Elements that can appear multiple times in a message, containing a variable-length field in the middle (whose length is specified by a preceding field) and ending with other static or dynamic fields.
- 6.1. IEEE 802.11 Add WLAN (src/elements/IEEE80211/AddWlan.h)
Strictly fixed-size elements that can appear multiple times in a message (typically for each Radio ID, WLAN ID, or Station MAC).
- 6.3. IEEE 802.11 Assigned WTP BSSID (src/elements/IEEE80211/AssignedWtpBssid.h)
- 6.4. IEEE 802.11 Delete WLAN (src/elements/IEEE80211/DeleteWlan.h)
- 6.5. IEEE 802.11 Direct Sequence Control (src/elements/IEEE80211/DirectSequenceControl.h)
- 6.7. IEEE 802.11 MAC Operation (src/elements/IEEE80211/MACOperation.h)
- 6.8. IEEE 802.11 MIC Countermeasures (src/elements/IEEE80211/MICCountermeasures.h)
- 6.9. IEEE 802.11 Multi-Domain Capability (src/elements/IEEE80211/MultiDomainCapability.h)
- 6.10. IEEE 802.11 OFDM Control (src/elements/IEEE80211/OFDMControl.h) — non-standard extension: the RFC 5416 "Reserved" octet is repurposed to carry the operating channel width
- 6.12. IEEE 802.11 RSNA Error Report From Station (src/elements/IEEE80211/RSNAErrorReportFromStation.h)
- 6.14. IEEE 802.11 Station QoS Profile (src/elements/IEEE80211/StationQoSProfile.h)
- 6.16. IEEE 802.11 Statistics (src/elements/IEEE80211/Statistics.h)
- 6.18. IEEE 802.11 Tx Power (src/elements/IEEE80211/TxPower.h)
- 6.20. IEEE 802.11 Update Station QoS (src/elements/IEEE80211/UpdateStationQoS.h)
- 6.22. IEEE 802.11 WTP Quality of Service (src/elements/IEEE80211/WTPQualityOfService.h)
- 6.23. IEEE 802.11 WTP Radio Configuration (src/elements/IEEE80211/WTPRadioConfiguration.h)
- 6.24. IEEE 802.11 WTP Radio Fail Alarm Indication (src/elements/IEEE80211/WTPRadioFailAlarmIndication.h)
- 6.25. IEEE 802.11 WTP Radio Information (src/elements/IEEE80211/WTPRadioInformation.h)
Elements that can appear multiple times in a message. Consist of initial static fields and end with a variable-length field (array of values, string, or raw data).
- 6.2. IEEE 802.11 Antenna (src/elements/IEEE80211/Antenna.h)
- 6.6. IEEE 802.11 Information Element (src/elements/IEEE80211/InformationElement.h)
- 6.11. IEEE 802.11 Rate Set (src/elements/IEEE80211/RateSet.h)
- 6.13. IEEE 802.11 Station (src/elements/IEEE80211/Station.h)
- 6.15. IEEE 802.11 Station Session Key (src/elements/IEEE80211/StationSessionKey.h)
- 6.17. IEEE 802.11 Supported Rates (src/elements/IEEE80211/SupportedRates.h)
- 6.19. IEEE 802.11 Tx Power Level (src/elements/IEEE80211/TxPowerLevel.h)
- 6.21. IEEE 802.11 Update WLAN (src/elements/IEEE80211/UpdateWlan.h)