fork SmartCAWPAP as FreeWTP

This commit is contained in:
Andreas Schultz
2016-08-22 16:59:55 +02:00
parent 8cc6559f08
commit 0101ea6e56
341 changed files with 724 additions and 17737 deletions

218
lib/Makefile.am Executable file
View File

@ -0,0 +1,218 @@
# FreeWTP -- An Open Source CAPWAP WTP
#
# Copyright SmartCAPWAP (C) 2012-2013 Massimo Vellucci <vemax78@gmail.com>
# Copyright FreeCAPWAP (C) 2016 Travelping GmbH <info@travelping.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program (see the file COPYING included with this
# distribution); if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
AM_CFLAGS = -std=gnu99 -D_GNU_SOURCE
noinst_LTLIBRARIES = libcapwap.la
libcapwap_la_LIBADD = -lwolfssl
libcapwap_la_SOURCES = \
capwap.c \
network.c \
protocol.c \
logging.c \
list.c \
array.c \
hash.c \
dtls.c \
dfa.c \
binding/ieee80211/ieee80211.c \
element.c \
element_acdescriptor.c \
element_acipv4list.c \
element_acipv6list.c \
element_acname.c \
element_acnamepriority.c \
element_actimestamp.c \
element_addmacacl.c \
element_addstation.c \
element_controlipv4.c \
element_controlipv6.c \
element_datatransferdata.c \
element_datatransfermode.c \
element_decrypterrorreport.c \
element_decrypterrorreportperiod.c \
element_deletemacacl.c \
element_deletestation.c \
element_discoverytype.c \
element_duplicateipv4.c \
element_duplicateipv6.c \
element_ecnsupport.c \
element_idletimeout.c \
element_imagedata.c \
element_imageidentifier.c \
element_imageinfo.c \
element_initdownload.c \
element_localipv4.c \
element_localipv6.c \
element_location.c \
element_maximumlength.c \
element_mtudiscovery.c \
element_radioadmstate.c \
element_radiooprstate.c \
element_resultcode.c \
element_returnedmessage.c \
element_sessionid.c \
element_statisticstimer.c \
element_timers.c \
element_transport.c \
element_vendorpayload.c \
element_wtpboarddata.c \
element_wtpdescriptor.c \
element_wtpfallback.c \
element_wtpframetunnelmode.c \
element_wtpmactype.c \
element_wtpname.c \
element_wtpradiostat.c \
element_wtprebootstat.c \
element_wtpstaticipaddress.c \
element_80211_addwlan.c \
element_80211_antenna.c \
element_80211_assignbssid.c \
element_80211_deletewlan.c \
element_80211_directsequencecontrol.c \
element_80211_ie.c \
element_80211_mac_profile.c \
element_80211_macoperation.c \
element_80211_miccountermeasures.c \
element_80211_multidomaincapability.c \
element_80211_ofdmcontrol.c \
element_80211_rateset.c \
element_80211_rsnaerrorreport.c \
element_80211_station.c \
element_80211_stationkey.c \
element_80211_stationqos.c \
element_80211_statistics.c \
element_80211_supported_mac_profiles.c \
element_80211_supportedrates.c \
element_80211_txpower.c \
element_80211_txpowerlevel.c \
element_80211_updatestationqos.c \
element_80211_updatewlan.c \
element_80211_wtpqos.c \
element_80211_wtpradioconf.c \
element_80211_wtpradiofailalarm.c \
element_80211_wtpradioinformation.c \
element_80211n_radioconf.c \
element_80211n_station_information.c \
element_vendor_travelping_wtp_timestamp.c \
element_vendor_travelping_80211_encryption_capability.c \
element_vendor_travelping_80211_update_key.c
noinst_HEADERS = \
error.h \
rfc.h \
capwap.h \
network.h \
protocol.h \
logging.h \
list.h \
array.h \
hash.h \
dtls.h \
capwap_dfa.h \
binding/ieee80211/ieee80211.c \
element.h \
element_acdescriptor.h \
element_acipv4list.h \
element_acipv6list.h \
element_acname.h \
element_acnamepriority.h \
element_actimestamp.h \
element_addmacacl.h \
element_addstation.h \
element_controlipv4.h \
element_controlipv6.h \
element_datatransferdata.h \
element_datatransfermode.h \
element_decrypterrorreport.h \
element_decrypterrorreportperiod.h \
element_deletemacacl.h \
element_deletestation.h \
element_discoverytype.h \
element_duplicateipv4.h \
element_duplicateipv6.h \
element_ecnsupport.h \
element_idletimeout.h \
element_imagedata.h \
element_imageidentifier.h \
element_imageinfo.h \
element_initdownload.h \
element_localipv4.h \
element_localipv6.h \
element_location.h \
element_maximumlength.h \
element_mtudiscovery.h \
element_radioadmstate.h \
element_radiooprstate.h \
element_resultcode.h \
element_returnedmessage.h \
element_sessionid.h \
element_statisticstimer.h \
element_timers.h \
element_transport.h \
element_vendorpayload.h \
element_wtpboarddata.h \
element_wtpdescriptor.h \
element_wtpfallback.h \
element_wtpframetunnelmode.h \
element_wtpmactype.h \
element_wtpname.h \
element_wtpradiostat.h \
element_wtprebootstat.h \
element_wtpstaticipaddress.h \
element_80211_addwlan.h \
element_80211_antenna.h \
element_80211_assignbssid.h \
element_80211_deletewlan.h \
element_80211_directsequencecontrol.h \
element_80211_ie.h \
element_80211_macoperation.h \
element_80211_mac_profile.h \
element_80211_miccountermeasures.h \
element_80211_multidomaincapability.h \
element_80211_ofdmcontrol.h \
element_80211_rateset.h \
element_80211_rsnaerrorreport.h \
element_80211_station.h \
element_80211_stationkey.h \
element_80211_stationqos.h \
element_80211_statistics.h \
element_80211_supported_mac_profiles.h \
element_80211_supportedrates.h \
element_80211_txpower.h \
element_80211_txpowerlevel.h \
element_80211_updatestationqos.h \
element_80211_updatewlan.h \
element_80211_wtpqos.h \
element_80211_wtpradioconf.h \
element_80211_wtpradiofailalarm.h \
element_80211_wtpradioinformation.h \
element_80211n_radioconf.h \
element_80211n_station_information.h \
element_vendor_travelping_wtp_timestamp.h \
element_vendor_travelping_80211_encryption_capability.h \
element_vendor_travelping_80211_update_key.h \
vendor_travelping.h
if DEBUG_BUILD
libcapwap_la_SOURCES += debug.c
noinst_HEADERS += debug.h
endif

91
lib/array.c Normal file
View File

@ -0,0 +1,91 @@
#include "capwap.h"
#include "array.h"
/* */
struct capwap_array* capwap_array_create(unsigned short itemsize, unsigned long initcount, int zeroed) {
struct capwap_array* array;
ASSERT(itemsize > 0);
array = (struct capwap_array*)capwap_alloc(sizeof(struct capwap_array));
memset(array, 0, sizeof(struct capwap_array));
array->itemsize = itemsize;
array->zeroed = zeroed;
if (initcount > 0) {
capwap_array_resize(array, initcount);
}
return array;
}
/* */
struct capwap_array* capwap_array_clone(struct capwap_array* array) {
struct capwap_array* clone;
ASSERT (array != NULL);
/* Clone array e items */
clone = capwap_array_create(array->itemsize, array->count, array->zeroed);
memcpy(clone->buffer, array->buffer, array->itemsize * array->count);
return clone;
}
/* */
void capwap_array_free(struct capwap_array* array) {
ASSERT(array != NULL);
if (array->buffer) {
capwap_free(array->buffer);
}
capwap_free(array);
}
/* */
void* capwap_array_get_item_pointer(struct capwap_array* array, unsigned long pos) {
ASSERT(array != NULL);
ASSERT((array->count == 0) || (array->buffer != NULL));
if (pos >= array->count) {
capwap_array_resize(array, pos + 1);
}
return (void*)(((char*)array->buffer) + array->itemsize * pos);
}
/* */
void capwap_array_resize(struct capwap_array* array, unsigned long count) {
int newcount;
void* newbuffer = NULL;
ASSERT(array != NULL);
ASSERT(array->itemsize > 0);
if (array->count == count) {
return;
}
newcount = min(array->count, count);
if (count > 0) {
newbuffer = capwap_alloc(array->itemsize * count);
/* Zeroed new items */
if (array->zeroed && (count > newcount)) {
memset(newbuffer + array->itemsize * newcount, 0, array->itemsize * (count - newcount));
}
}
if (array->buffer) {
if ((newbuffer != NULL) && (newcount > 0)) {
memcpy(newbuffer, array->buffer, array->itemsize * newcount);
}
capwap_free(array->buffer);
}
array->buffer = newbuffer;
array->count = count;
}

17
lib/array.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef __CAPWAP_ARRAY_HEADER__
#define __CAPWAP_ARRAY_HEADER__
struct capwap_array {
void* buffer;
unsigned short itemsize;
unsigned long count;
int zeroed;
};
struct capwap_array* capwap_array_create(unsigned short itemsize, unsigned long initcount, int zeroed);
struct capwap_array* capwap_array_clone(struct capwap_array* array);
void capwap_array_free(struct capwap_array* array);
void* capwap_array_get_item_pointer(struct capwap_array* array, unsigned long pos);
void capwap_array_resize(struct capwap_array* array, unsigned long count);
#endif /* __CAPWAP_ARRAY_HEADER__ */

View File

@ -0,0 +1,790 @@
#include "capwap.h"
#include "ieee80211.h"
/* */
static int ieee80211_ie_set_ssid(uint8_t* buffer, const char* ssid, int hidessid) {
struct ieee80211_ie_ssid* iessid = (struct ieee80211_ie_ssid*)buffer;
ASSERT(buffer != NULL);
ASSERT(ssid != NULL);
iessid->id = IEEE80211_IE_SSID;
if (hidessid) {
iessid->len = 0;
} else {
iessid->len = strlen(ssid);
if (iessid->len > IEEE80211_IE_SSID_MAX_LENGTH) {
return -1;
}
strncpy((char*)iessid->ssid, ssid, iessid->len);
}
return sizeof(struct ieee80211_ie_ssid) + iessid->len;
}
/* */
static int ieee80211_ie_set_supportedrates(uint8_t* buffer, uint8_t* supportedrates, int supportedratescount) {
int i;
int count;
struct ieee80211_ie_supported_rates* iesupportedrates = (struct ieee80211_ie_supported_rates*)buffer;
ASSERT(buffer != NULL);
ASSERT(supportedrates != NULL);
ASSERT(supportedratescount > 0);
/* IE accept max only 8 rate */
count = supportedratescount;
if (count > 8) {
count = 8;
}
/* */
iesupportedrates->id = IEEE80211_IE_SUPPORTED_RATES;
iesupportedrates->len = count;
for (i = 0; i < count; i++) {
iesupportedrates->rates[i] = supportedrates[i];
}
return sizeof(struct ieee80211_ie_supported_rates) + iesupportedrates->len;
}
/* */
static int ieee80211_ie_set_extendedsupportedrates(uint8_t* buffer, uint8_t* supportedrates, int supportedratescount) {
int i, j;
struct ieee80211_ie_extended_supported_rates* ieextendedsupportedrates = (struct ieee80211_ie_extended_supported_rates*)buffer;
ASSERT(buffer != NULL);
ASSERT(supportedrates != NULL);
/* IE accept only > 8 rate */
if (supportedratescount <= IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH) {
return 0;
}
/* */
ieextendedsupportedrates->id = IEEE80211_IE_EXTENDED_SUPPORTED_RATES;
ieextendedsupportedrates->len = supportedratescount - IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH;
for (i = IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH, j = 0; i < supportedratescount; i++, j++) {
ieextendedsupportedrates->rates[j] = supportedrates[i];
}
return sizeof(struct ieee80211_ie_extended_supported_rates) + ieextendedsupportedrates->len;
}
/* */
static int ieee80211_ie_set_dsss(uint8_t* buffer, uint8_t channel) {
struct ieee80211_ie_dsss* iedsss = (struct ieee80211_ie_dsss*)buffer;
ASSERT(buffer != NULL);
iedsss->id = IEEE80211_IE_DSSS;
iedsss->len = IEEE80211_IE_DSSS_LENGTH;
iedsss->channel = channel;
return sizeof(struct ieee80211_ie_dsss);
}
/* */
static int ieee80211_ie_set_erp(uint8_t* buffer, uint32_t mode, uint8_t erpinfo) {
struct ieee80211_ie_erp* ieerp = (struct ieee80211_ie_erp*)buffer;
ASSERT(buffer != NULL);
if (!(mode & IEEE80211_RADIO_TYPE_80211G)) {
return 0;
}
ieerp->id = IEEE80211_IE_ERP;
ieerp->len = IEEE80211_IE_ERP_LENGTH;
ieerp->params = erpinfo;
return sizeof(struct ieee80211_ie_erp);
}
/* */
int ieee80211_retrieve_information_elements_position(struct ieee80211_ie_items* items, const uint8_t* data, int length) {
ASSERT(items != NULL);
ASSERT(data != NULL);
/* */
memset(items, 0, sizeof(struct ieee80211_ie_items));
/* Parsing */
while (length >= 2) {
struct ieee80211_ie *ie = (struct ieee80211_ie *)data;
/* Parsing Information Element */
switch (ie->id) {
case IEEE80211_IE_SSID:
if (ie->len > IEEE80211_IE_SSID_MAX_LENGTH)
return -1;
items->ssid = (struct ieee80211_ie_ssid *)data;
break;
case IEEE80211_IE_SUPPORTED_RATES:
if ((ie->len < IEEE80211_IE_SUPPORTED_RATES_MIN_LENGTH) ||
(ie->len > IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH))
return -1;
items->supported_rates = (struct ieee80211_ie_supported_rates *)data;
break;
case IEEE80211_IE_DSSS:
if (ie->len != IEEE80211_IE_DSSS_LENGTH)
return -1;
items->dsss = (struct ieee80211_ie_dsss *)data;
break;
case IEEE80211_IE_COUNTRY:
if (ie->len < IEEE80211_IE_COUNTRY_MIN_LENGTH)
return -1;
items->country = (struct ieee80211_ie_country *)data;
break;
case IEEE80211_IE_CHALLENGE_TEXT:
if (ie->len < IEEE80211_IE_CHALLENGE_TEXT_MIN_LENGTH)
return -1;
items->challenge_text = (struct ieee80211_ie_challenge_text *)data;
break;
case IEEE80211_IE_ERP:
if (ie->len != IEEE80211_IE_ERP_LENGTH)
return -1;
items->erp = (struct ieee80211_ie_erp *)data;
break;
case IEEE80211_IE_EXTENDED_SUPPORTED_RATES:
if (ie->len < IEEE80211_IE_EXTENDED_SUPPORTED_MIN_LENGTH)
return -1;
items->extended_supported_rates =
(struct ieee80211_ie_extended_supported_rates *)data;
break;
case IEEE80211_IE_EDCA_PARAMETER_SET:
if (ie->len != IEEE80211_IE_EDCA_PARAMETER_SET_LENGTH)
return -1;
items->edca_parameter_set = (struct ieee80211_ie_edca_parameter_set *)data;
break;
case IEEE80211_IE_QOS_CAPABILITY:
if (ie->len != IEEE80211_IE_QOS_CAPABILITY_LENGTH)
return -1;
items->qos_capability = (struct ieee80211_ie_qos_capability *)data;
break;
case IEEE80211_IE_POWER_CONSTRAINT:
if (ie->len != IEEE80211_IE_POWER_CONSTRAINT_LENGTH)
return -1;
items->power_constraint = (struct ieee80211_ie_power_constraint *)data;
break;
case IEEE80211_IE_SSID_LIST:
items->ssid_list = (struct ieee80211_ie_ssid_list *)data;
break;
case IEEE80211_IE_VENDOR_SPECIFIC: {
struct ieee80211_ie_vendor_specific *vs =
(struct ieee80211_ie_vendor_specific *)data;
uint32_t oui = vs->oui[0] << 16 | vs->oui[1] << 8 | vs->oui[2];
if (oui == MICROSOFT_OUI &&
vs->oui_type == WMM_TYPE &&
vs->oui_subtype == WMM_INFORMATION_ELEMENT) {
items->wmm_ie = (struct ieee80211_ie_wmm_information_element *)data;
break;
}
}
}
/* Next Information Element */
data += sizeof(struct ieee80211_ie) + ie->len;
length -= sizeof(struct ieee80211_ie) + ie->len;
}
return (!length ? 0 : -1);
}
/* */
int ieee80211_aid_create(uint32_t* aidbitfield, uint16_t* aid) {
int i, j;
ASSERT(aidbitfield != NULL);
ASSERT(aid != NULL);
/* Search free aid bitfield */
for (i = 0; i < IEEE80211_AID_BITFIELD_SIZE; i++) {
if (aidbitfield[i] != 0xffffffff) {
uint32_t bitfield = aidbitfield[i];
/* Search free bit */
for (j = 0; j < 32; j++) {
if (!(bitfield & (1 << j))) {
*aid = i * 32 + j + 1;
if (*aid <= IEEE80211_AID_MAX_VALUE) {
aidbitfield[i] |= (1 << j);
return 0;
}
break;
}
}
break;
}
}
*aid = 0;
return -1;
}
/* */
void ieee80211_aid_free(uint32_t* aidbitfield, uint16_t aid) {
ASSERT(aidbitfield != NULL);
ASSERT((aid > 0) && (aid <= IEEE80211_AID_MAX_VALUE));
aidbitfield[(aid - 1) / 32] &= ~(1 << ((aid - 1) % 32));
}
/* */
unsigned long ieee80211_frequency_to_channel(uint32_t freq) {
if ((freq >= 2412) && (freq <= 2472)) {
return (freq - 2407) / 5;
} else if (freq == 2484) {
return 14;
} else if ((freq >= 4915) && (freq <= 4980)) {
return (freq - 4000) / 5;
} else if ((freq >= 5035) && (freq <= 5825)) {
return (freq - 5000) / 5;
}
return 0;
}
/* */
int ieee80211_is_broadcast_addr(const uint8_t* addr) {
return (((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)) ? 1 : 0);
}
/* */
const uint8_t* ieee80211_get_sa_addr(const struct ieee80211_header* header) {
uint16_t framecontrol;
uint16_t framecontrol_type;
ASSERT(header);
/* Get type frame */
framecontrol = __le16_to_cpu(header->framecontrol);
framecontrol_type = IEEE80211_FRAME_CONTROL_GET_TYPE(framecontrol);
if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_MGMT) {
return header->address2;
} else if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_DATA) {
switch (framecontrol & (IEEE80211_FRAME_CONTROL_MASK_TODS | IEEE80211_FRAME_CONTROL_MASK_FROMDS)) {
case 0: {
return header->address2;
}
case IEEE80211_FRAME_CONTROL_MASK_TODS: {
return header->address2;
}
case IEEE80211_FRAME_CONTROL_MASK_FROMDS: {
return header->address3;
}
}
}
return NULL;
}
const uint8_t* ieee80211_get_da_addr(const struct ieee80211_header* header) {
uint16_t framecontrol;
uint16_t framecontrol_type;
ASSERT(header);
/* Get type frame */
framecontrol = __le16_to_cpu(header->framecontrol);
framecontrol_type = IEEE80211_FRAME_CONTROL_GET_TYPE(framecontrol);
if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_MGMT) {
return header->address1;
} else if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_DATA) {
switch (framecontrol & (IEEE80211_FRAME_CONTROL_MASK_TODS | IEEE80211_FRAME_CONTROL_MASK_FROMDS)) {
case 0: {
return header->address1;
}
case IEEE80211_FRAME_CONTROL_MASK_TODS: {
return header->address3;
}
case IEEE80211_FRAME_CONTROL_MASK_FROMDS: {
return header->address1;
}
}
}
return NULL;
}
/* */
const uint8_t* ieee80211_get_bssid_addr(const struct ieee80211_header* header) {
uint16_t framecontrol;
uint16_t framecontrol_type;
ASSERT(header);
/* Get type frame */
framecontrol = __le16_to_cpu(header->framecontrol);
framecontrol_type = IEEE80211_FRAME_CONTROL_GET_TYPE(framecontrol);
if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_MGMT) {
return header->address3;
} else if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_DATA) {
switch (framecontrol & (IEEE80211_FRAME_CONTROL_MASK_TODS | IEEE80211_FRAME_CONTROL_MASK_FROMDS)) {
case 0: {
return header->address3;
}
case IEEE80211_FRAME_CONTROL_MASK_TODS: {
return header->address1;
}
case IEEE80211_FRAME_CONTROL_MASK_FROMDS: {
return header->address2;
}
}
}
return NULL;
}
/* */
int ieee80211_is_valid_ssid(const char* ssid, struct ieee80211_ie_ssid* iessid, struct ieee80211_ie_ssid_list* isssidlist) {
int ssidlength;
ASSERT(ssid != NULL);
if (!iessid) {
return IEEE80211_WRONG_SSID;
}
/* Check SSID */
ssidlength = strlen((char*)ssid);
if ((ssidlength == iessid->len) && !memcmp(ssid, iessid->ssid, ssidlength)) {
return IEEE80211_VALID_SSID;
}
/* Check SSID list */
if (isssidlist) {
int length = isssidlist->len;
uint8_t* pos = isssidlist->lists;
while (length >= sizeof(struct ieee80211_ie)) {
struct ieee80211_ie_ssid* ssiditem = (struct ieee80211_ie_ssid*)pos;
/* Check buffer */
length -= sizeof(struct ieee80211_ie);
if ((ssiditem->id != IEEE80211_IE_SSID) || !ssiditem->len || (length < ssiditem->len)) {
break;
} else if ((ssidlength == ssiditem->len) && !memcmp(ssid, ssiditem->ssid, ssidlength)) {
return IEEE80211_VALID_SSID;
}
/* Next */
length -= ssiditem->len;
pos += sizeof(struct ieee80211_ie) + ssiditem->len;
}
}
return (!iessid->len ? IEEE80211_WILDCARD_SSID : IEEE80211_WRONG_SSID);
}
/* */
uint8_t ieee80211_get_erpinfo(uint32_t mode, int olbc, unsigned long stationnonerpcount, unsigned long stationnoshortpreamblecount, int shortpreamble) {
uint8_t result = 0;
/* Erp mode is valid only in IEEE 802.11 g*/
if (mode & IEEE80211_RADIO_TYPE_80211G) {
if (olbc) {
result |= IEEE80211_ERP_INFO_USE_PROTECTION;
}
if (stationnonerpcount > 0) {
result |= (IEEE80211_ERP_INFO_NON_ERP_PRESENT | IEEE80211_ERP_INFO_USE_PROTECTION);
}
if (!shortpreamble || (stationnoshortpreamblecount > 0)) {
result |= IEEE80211_ERP_INFO_BARKER_PREAMBLE_MODE;
}
}
return result;
}
/* */
int ieee80211_create_beacon(uint8_t* buffer, int length, struct ieee80211_beacon_params* params) {
int result;
uint8_t* pos;
struct ieee80211_header_mgmt* header;
ASSERT(buffer != NULL);
/* */
header = (struct ieee80211_header_mgmt*)buffer;
params->headbeacon = buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT,
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_BEACON);
header->durationid = __cpu_to_le16(0);
memset(header->da, 0xff, ETH_ALEN);
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->sequencecontrol = __cpu_to_le16(0);
memset(header->beacon.timestamp, 0, sizeof(header->beacon.timestamp));
header->beacon.beaconinterval = __cpu_to_le16(params->beaconperiod);
header->beacon.capability = __cpu_to_le16(params->capability);
/* Header frame size */
params->headbeaconlength = (int)((uint8_t*)&header->beacon.ie[0] - (uint8_t*)header);
pos = buffer + params->headbeaconlength;
/* Information Element: SSID */
result = ieee80211_ie_set_ssid(pos, params->ssid, (params->ssid_hidden ? 1 : 0));
if (result < 0) {
return -1;
}
pos += result;
params->headbeaconlength += result;
/* Information Element: Supported Rates */
result = ieee80211_ie_set_supportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
params->headbeaconlength += result;
/* Information Element: DSSS */
result = ieee80211_ie_set_dsss(pos, params->channel);
if (result < 0) {
return -1;
}
pos += result;
params->headbeaconlength += result;
/* Separate Information Elements into two block between IE TIM */
params->tailbeacon = pos;
params->tailbeaconlength = 0;
/* Information Element: Country */
/* TODO */
/* Information Element: ERP */
result = ieee80211_ie_set_erp(pos, params->mode, params->erpinfo);
if (result < 0) {
return -1;
}
pos += result;
params->tailbeaconlength += result;
/* Information Element: Extended Supported Rates */
result = ieee80211_ie_set_extendedsupportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
params->tailbeaconlength += result;
log_printf(LOG_DEBUG, "IEEE80211: Beacon IE length: %d", params->beacon_ies_len);
if (params->beacon_ies_len) {
log_hexdump(LOG_DEBUG, "IEEE80211: Beacon IEs",
params->beacon_ies, params->beacon_ies_len);
memcpy(pos, params->beacon_ies, params->beacon_ies_len);
pos += params->beacon_ies_len;
params->tailbeaconlength += params->beacon_ies_len;
}
/* Probe Response offload */
if (params->flags & IEEE80221_CREATE_BEACON_FLAGS_PROBE_RESPONSE_OFFLOAD) {
struct ieee80211_probe_response_params proberesponseparams;
/* */
memset(&proberesponseparams, 0, sizeof(struct ieee80211_probe_response_params));
memcpy(proberesponseparams.bssid, params->bssid, ETH_ALEN);
proberesponseparams.beaconperiod = params->beaconperiod;
proberesponseparams.capability = params->capability;
proberesponseparams.ssid = params->ssid;
memcpy(proberesponseparams.supportedrates, params->supportedrates, params->supportedratescount);
proberesponseparams.supportedratescount = params->supportedratescount;
proberesponseparams.mode = params->mode;
proberesponseparams.erpinfo = params->erpinfo;
proberesponseparams.channel = params->channel;
/* */
params->proberesponseoffload = pos;
params->proberesponseoffloadlength = ieee80211_create_probe_response(pos, (int)(pos - buffer), &proberesponseparams);
if (params->proberesponseoffloadlength < 0) {
return -1;
}
/* */
pos += params->proberesponseoffloadlength;
log_printf(LOG_DEBUG, "IEEE80211: Probe Response IE length: %d", params->response_ies_len);
if (params->response_ies_len) {
log_hexdump(LOG_DEBUG, "IEEE80211: Probe Response IEs",
params->response_ies, params->response_ies_len);
memcpy(pos, params->response_ies, params->response_ies_len);
pos += params->response_ies_len;
params->proberesponseoffloadlength += params->response_ies_len;
}
}
return (int)(pos - buffer);
}
/* */
int ieee80211_create_probe_response(uint8_t* buffer, int length, struct ieee80211_probe_response_params* params) {
int result;
uint8_t* pos;
int responselength;
struct ieee80211_header_mgmt* header;
ASSERT(buffer != NULL);
/* */
header = (struct ieee80211_header_mgmt*)buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT, IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_PROBE_RESPONSE);
header->durationid = __cpu_to_le16(0);
memcpy(header->da, params->station, ETH_ALEN);
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->sequencecontrol = __cpu_to_le16(0);
memset(header->proberesponse.timestamp, 0, sizeof(header->proberesponse.timestamp));
header->proberesponse.beaconinterval = __cpu_to_le16(params->beaconperiod);
header->proberesponse.capability = __cpu_to_le16(params->capability);
/* Header frame size */
responselength = (int)((uint8_t*)&header->proberesponse.ie[0] - (uint8_t*)header);
pos = buffer + responselength;
/* Information Element: SSID */
result = ieee80211_ie_set_ssid(pos, params->ssid, 0);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: Supported Rates */
result = ieee80211_ie_set_supportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: DSSS */
result = ieee80211_ie_set_dsss(pos, params->channel);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: Country */
/* TODO */
/* Information Element: ERP */
result = ieee80211_ie_set_erp(pos, params->mode, params->erpinfo);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: Extended Supported Rates */
result = ieee80211_ie_set_extendedsupportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
log_printf(LOG_DEBUG, "IEEE80211: Probe Response IE length: %d", params->response_ies_len);
if (params->response_ies_len) {
log_hexdump(LOG_DEBUG, "IEEE80211: Response IEs",
params->response_ies, params->response_ies_len);
memcpy(pos, params->response_ies, params->response_ies_len);
/* pos += params->response_ies_len; */ /* Comment for disable Dead inscrement Clang Analyzer warning */
responselength += params->response_ies_len;
}
return responselength;
}
/* */
int ieee80211_create_authentication_response(uint8_t* buffer, int length, struct ieee80211_authentication_params* params) {
int responselength;
struct ieee80211_header_mgmt* header;
ASSERT(buffer != NULL);
/* */
header = (struct ieee80211_header_mgmt*)buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT, IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_AUTHENTICATION);
header->durationid = __cpu_to_le16(0);
memcpy(header->da, params->station, ETH_ALEN);
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->sequencecontrol = __cpu_to_le16(0);
header->authetication.algorithm = __cpu_to_le16(params->algorithm);
header->authetication.transactionseqnumber = __cpu_to_le16(params->transactionseqnumber);
header->authetication.statuscode = __cpu_to_le16(params->statuscode);
/* Header frame size */
responselength = (int)((uint8_t*)&header->authetication.ie[0] - (uint8_t*)header);
/* TODO: add custon IE */
return responselength;
}
/* */
int ieee80211_create_associationresponse_response(uint8_t* buffer, int length, struct ieee80211_associationresponse_params* params) {
uint8_t* pos;
int result;
int responselength;
struct ieee80211_header_mgmt* header;
ASSERT(buffer != NULL);
/* */
header = (struct ieee80211_header_mgmt*)buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT,
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_RESPONSE);
header->durationid = __cpu_to_le16(0);
memcpy(header->da, params->station, ETH_ALEN);
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->sequencecontrol = __cpu_to_le16(0);
header->associationresponse.capability = __cpu_to_le16(params->capability);
header->associationresponse.statuscode = __cpu_to_le16(params->statuscode);
header->associationresponse.aid = __cpu_to_le16(params->aid);
/* Header frame size */
responselength = (int)((uint8_t*)&header->associationresponse.ie[0] - (uint8_t*)header);
pos = buffer + responselength;
/* Information Element: Supported Rates */
result = ieee80211_ie_set_supportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: Extended Supported Rates */
result = ieee80211_ie_set_extendedsupportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
log_printf(LOG_DEBUG, "IEEE80211: Association Response IE length: %d", params->response_ies_len);
if (params->response_ies_len) {
log_hexdump(LOG_DEBUG, "IEEE80211: Response IEs",
params->response_ies, params->response_ies_len);
memcpy(pos, params->response_ies, params->response_ies_len);
/* pos += params->response_ies_len; */ /* Comment for disable Dead inscrement Clang Analyzer warning */
responselength += params->response_ies_len;
}
return responselength;
}
/* */
int ieee80211_create_deauthentication(uint8_t* buffer, int length, struct ieee80211_deauthentication_params* params) {
struct ieee80211_header_mgmt* header;
ASSERT(buffer != NULL);
/* */
header = (struct ieee80211_header_mgmt*)buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT, IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DEAUTHENTICATION);
header->durationid = __cpu_to_le16(0);
memcpy(header->da, params->station, ETH_ALEN);
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->sequencecontrol = __cpu_to_le16(0);
header->deauthetication.reasoncode = __cpu_to_le16(params->reasoncode);
return (int)((uint8_t*)&header->deauthetication.ie[0] - (uint8_t*)header);
}
/* */
int ieee80211_create_disassociation(uint8_t* buffer, int length,
struct ieee80211_disassociation_params* params)
{
struct ieee80211_header_mgmt* header;
ASSERT(buffer != NULL);
/* */
header = (struct ieee80211_header_mgmt*)buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT,
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DISASSOCIATION);
header->durationid = __cpu_to_le16(0);
memcpy(header->da, params->station, ETH_ALEN);
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->sequencecontrol = __cpu_to_le16(0);
header->disassociation.reasoncode = __cpu_to_le16(params->reasoncode);
return (int)((uint8_t*)&header->disassociation.ie[0] - (uint8_t*)header);
}

View File

@ -0,0 +1,751 @@
#ifndef __CAPWAP_IEEE802_11_HEADER__
#define __CAPWAP_IEEE802_11_HEADER__
#include <linux/types.h>
#include <asm/byteorder.h>
#include <linux/if_ether.h>
#ifndef STRUCT_PACKED
#define STRUCT_PACKED __attribute__((__packed__))
#endif
/* Global values */
#define IEEE80211_MTU 7981
#define IEEE80211_SUPPORTEDRATE_MAX_COUNT 16
#define IEEE80211_MAX_STATIONS 2007
#define IEEE80211_SSID_MAX_LENGTH 32
/* Radio type with value same of IEEE802.11 Radio Information Message Element */
#define IEEE80211_RADIO_TYPE_80211B 0x00000001
#define IEEE80211_RADIO_TYPE_80211A 0x00000002
#define IEEE80211_RADIO_TYPE_80211G 0x00000004
#define IEEE80211_RADIO_TYPE_80211N 0x00000008
/* */
#define IS_IEEE80211_FREQ_BG(x) (((x >= 2412) && (x <= 2484)) ? 1 : 0)
#define IS_IEEE80211_FREQ_A(x) ((((x >= 4915) && (x <= 4980)) || ((x >= 5035) && (x <= 5825))) ? 1 : 0)
/* Rate into multiple of 500Kbps */
#define IEEE80211_RATE_1M 2
#define IEEE80211_RATE_2M 4
#define IEEE80211_RATE_5_5M 11
#define IEEE80211_RATE_11M 22
#define IEEE80211_RATE_6M 12
#define IEEE80211_RATE_9M 18
#define IEEE80211_RATE_12M 24
#define IEEE80211_RATE_18M 36
#define IEEE80211_RATE_24M 48
#define IEEE80211_RATE_36M 72
#define IEEE80211_RATE_48M 96
#define IEEE80211_RATE_54M 108
#define IEEE80211_RATE_80211N 127
#define IS_IEEE80211_RATE_B(x) (((x == IEEE80211_RATE_1M) || (x == IEEE80211_RATE_2M) || (x == IEEE80211_RATE_5_5M) || (x == IEEE80211_RATE_11M)) ? 1 : 0)
#define IS_IEEE80211_RATE_G(x) (((x == IEEE80211_RATE_6M) || (x == IEEE80211_RATE_9M) || (x == IEEE80211_RATE_12M) || (x == IEEE80211_RATE_18M) || (x == IEEE80211_RATE_24M) || (x == IEEE80211_RATE_36M) || (x == IEEE80211_RATE_48M) || (x == IEEE80211_RATE_54M)) ? 1 : 0)
#define IS_IEEE80211_RATE_A(x) (((x == IEEE80211_RATE_6M) || (x == IEEE80211_RATE_9M) || (x == IEEE80211_RATE_12M) || (x == IEEE80211_RATE_18M) || (x == IEEE80211_RATE_24M) || (x == IEEE80211_RATE_36M) || (x == IEEE80211_RATE_48M) || (x == IEEE80211_RATE_54M)) ? 1 : 0)
#define IS_IEEE80211_RATE_N(x) ((x == IEEE80211_RATE_80211N) ? 1 : 0)
#define IEEE80211_BASICRATE 128
#define IS_IEEE80211_BASICRATE_B(x) ((x == IEEE80211_RATE_1M) || (x == IEEE80211_RATE_2M))
#define IS_IEEE80211_BASICRATE_G(x) ((x == IEEE80211_RATE_6M) || (x == IEEE80211_RATE_9M) || (x == IEEE80211_RATE_12M) || (x == IEEE80211_RATE_18M))
#define IS_IEEE80211_BASICRATE_BG(x) ((x == IEEE80211_RATE_1M) || (x == IEEE80211_RATE_2M) || (x == IEEE80211_RATE_5_5M) || (x == IEEE80211_RATE_11M))
#define IS_IEEE80211_BASICRATE_A(x) ((x == IEEE80211_RATE_6M) || (x == IEEE80211_RATE_12M) || (x == IEEE80211_RATE_24M))
/* Frame control type */
#define IEEE80211_FRAMECONTROL_TYPE_MGMT 0
#define IEEE80211_FRAMECONTROL_TYPE_CTRL 1
#define IEEE80211_FRAMECONTROL_TYPE_DATA 2
/* Frame control Management subtype */
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_REQUEST 0
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_RESPONSE 1
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_REASSOCIATION_REQUEST 2
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_REASSOCIATION_RESPONSE 3
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_PROBE_REQUEST 4
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_PROBE_RESPONSE 5
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_TIMING_ADV 6
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_BEACON 8
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ATIM 9
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DISASSOCIATION 10
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_AUTHENTICATION 11
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DEAUTHENTICATION 12
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ACTION 13
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ACTION_NOACK 14
/* Frame control Control subtype */
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_CTRLWRAPPER 7
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_BLOCKACK_REQ 8
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_BLOCKACK 9
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_PSPOLL 10
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_RTS 11
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_CTS 12
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_ACK 13
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_CFEND 14
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_CFEND_CFACK 15
/* Frame control Data subtype */
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_DATA 0
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_DATA_CFACK 1
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_DATA_CFPOLL 2
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_DATA_CFACK_CFPOLL 3
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_NULL 4
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_CFACK 5
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_CFPOLL 6
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_CFACK_CFPOLL 7
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSDATA 8
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSDATA_CFACK 9
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSDATA_CFPOLL 10
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSDATA_CFACK_CFPOLL 11
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSNULL 12
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSCFPOLL 14
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSCFACK_CFPOLL 15
/* */
#define IEEE80211_FRAME_CONTROL_MASK_PROTOCOL_VERSION 0x0003
#define IEEE80211_FRAME_CONTROL_MASK_TYPE 0x000c
#define IEEE80211_FRAME_CONTROL_MASK_SUBTYPE 0x00f0
#define IEEE80211_FRAME_CONTROL_MASK_TODS 0x0100
#define IEEE80211_FRAME_CONTROL_MASK_FROMDS 0x0200
#define IEEE80211_FRAME_CONTROL_MASK_MORE_FRAGMENT 0x0400
#define IEEE80211_FRAME_CONTROL_MASK_RETRY 0x0800
#define IEEE80211_FRAME_CONTROL_MASK_POWER_MANAGEMENT 0x1000
#define IEEE80211_FRAME_CONTROL_MASK_MORE_DATA 0x2000
#define IEEE80211_FRAME_CONTROL_MASK_PROTECTED_FRAME 0x4000
#define IEEE80211_FRAME_CONTROL_MASK_ORDER 0x8000
#define IEEE80211_FRAME_CONTROL(type, stype) __cpu_to_le16((type << 2) | (stype << 4))
#define IEEE80211_FRAME_CONTROL_GET_TYPE(framecontrol) (((framecontrol) & IEEE80211_FRAME_CONTROL_MASK_TYPE) >> 2)
#define IEEE80211_FRAME_CONTROL_GET_SUBTYPE(framecontrol) (((framecontrol) & IEEE80211_FRAME_CONTROL_MASK_SUBTYPE) >> 4)
/* IEEE802.11 Status Code */
#define IEEE80211_STATUS_SUCCESS 0
#define IEEE80211_STATUS_UNSPECIFIED_FAILURE 1
#define IEEE80211_STATUS_TDLS_WAKEUP_ALTERNATE 2
#define IEEE80211_STATUS_TDLS_WAKEUP_REJECT 3
#define IEEE80211_STATUS_SECURITY_DISABLED 5
#define IEEE80211_STATUS_UNACCEPTABLE_LIFETIME 6
#define IEEE80211_STATUS_NOT_IN_SAME_BSS 7
#define IEEE80211_STATUS_CAPS_UNSUPPORTED 10
#define IEEE80211_STATUS_REASSOCIATION_NO_ASSOCIATE 11
#define IEEE80211_STATUS_ASSOCIATION_DENIED_UNSPEC 12
#define IEEE80211_STATUS_NOT_SUPPORTED_AUTHENTICATION_ALGORITHM 13
#define IEEE80211_STATUS_UNKNOWN_AUTHENTICATION_TRANSACTION 14
#define IEEE80211_STATUS_CHALLENGE_FAIL 15
#define IEEE80211_STATUS_AUTHENTICATION_TIMEOUT 16
#define IEEE80211_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
#define IEEE80211_STATUS_ASSOCIATION_DENIED_RATES 18
#define IEEE80211_STATUS_ASSOCIATION_DENIED_NOSHORT 19
#define IEEE80211_STATUS_ASSOCIATION_DENIED_NOPBCC 20
#define IEEE80211_STATUS_ASSOCIATION_DENIED_NOAGILITY 21
#define IEEE80211_STATUS_SPEC_MGMT_REQUIRED 22
#define IEEE80211_STATUS_PWR_CAPABILITY_NOT_VALID 23
#define IEEE80211_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24
#define IEEE80211_STATUS_ASSOCIATION_DENIED_NO_SHORT_SLOT_TIME 25
#define IEEE80211_STATUS_ASSOCIATION_DENIED_NO_DSSS_OFDM 26
#define IEEE80211_STATUS_ASSOCIATION_DENIED_NO_HT 27
#define IEEE80211_STATUS_R0KH_UNREACHABLE 28
#define IEEE80211_STATUS_ASSOCIATION_DENIED_NO_PCO 29
#define IEEE80211_STATUS_ASSOCIATION_REJECTED_TEMPORARILY 30
#define IEEE80211_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
#define IEEE80211_STATUS_UNSPECIFIED_QOS_FAILURE 32
#define IEEE80211_STATUS_QOS_INSUFFICIENT_BANDWIDTH 33
#define IEEE80211_STATUS_EXCESSIVE_FRAME_LOST 34
#define IEEE80211_STATUS_STA_NOT_SUPPORT_QOS_FACILITY 35
#define IEEE80211_STATUS_REQUEST_DECLINED 37
#define IEEE80211_STATUS_INVALID_PARAMETERS 38
#define IEEE80211_STATUS_REJECTED_WITH_SUGGESTED_CHANGES 39
#define IEEE80211_STATUS_INVALID_IE 40
#define IEEE80211_STATUS_GROUP_CIPHER_NOT_VALID 41
#define IEEE80211_STATUS_PAIRWISE_CIPHER_NOT_VALID 42
#define IEEE80211_STATUS_AKMP_NOT_VALID 43
#define IEEE80211_STATUS_UNSUPPORTED_RSN_IE_VERSION 44
#define IEEE80211_STATUS_INVALID_RSN_IE_CAPAB 45
#define IEEE80211_STATUS_CIPHER_REJECTED_PER_POLICY 46
#define IEEE80211_STATUS_TS_NOT_CREATED 47
#define IEEE80211_STATUS_DIRECT_LINK_NOT_ALLOWED 48
#define IEEE80211_STATUS_DEST_STA_NOT_PRESENT 49
#define IEEE80211_STATUS_DEST_STA_NOT_QOS_STA 50
#define IEEE80211_STATUS_ASSOCIATION_DENIED_LISTEN_INT_TOO_LARGE 51
#define IEEE80211_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52
#define IEEE80211_STATUS_INVALID_PMKID 53
#define IEEE80211_STATUS_INVALID_MDIE 54
#define IEEE80211_STATUS_INVALID_FTIE 55
#define IEEE80211_STATUS_REQUEST_TCLAS_NOT_SUPPORTED 56
#define IEEE80211_STATUS_INSUFFICIENT_TCLAS 57
#define IEEE80211_STATUS_TS_NOT_BEEN_CREATED 58
#define IEEE80211_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED 59
#define IEEE80211_STATUS_NO_OUTSTANDING_GAS_REQ 60
#define IEEE80211_STATUS_GAS_RESP_NOT_RECEIVED 61
#define IEEE80211_STATUS_STA_TIMED_OUT_WAITING_FOR_GAS_RESP 62
#define IEEE80211_STATUS_GAS_RESP_LARGER_THAN_LIMIT 63
#define IEEE80211_STATUS_REQ_REFUSED_HOME 64
#define IEEE80211_STATUS_ADV_SRV_UNREACHABLE 65
#define IEEE80211_STATUS_REQ_REFUSED_SSPN 67
#define IEEE80211_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68
#define IEEE80211_STATUS_INVALID_RSNIE 72
#define IEEE80211_STATUS_UAPSD_COEXISTENCE_NOT_SUPPORTED 73
#define IEEE80211_STATUS_REQUEST_UAPSD_COEXISTENCE_NOT_SUPPORTED 74
#define IEEE80211_STATUS_REQUEST_INTERVAL_NOT SUPPORTED 75
#define IEEE80211_STATUS_ANTI_CLOGGING_TOKEN_REQ 76
#define IEEE80211_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77
#define IEEE80211_STATUS_CANNOT_FIND_ALTERNATIVE_TBTT 78
#define IEEE80211_STATUS_TRANSMISSION_FAILURE 79
#define IEEE80211_STATUS_REQUYESTED_TCLAS_NOT_SUPPORTED 80
#define IEEE80211_STATUS_TCLAS_RESOURCES_EXHAUSTED 81
#define IEEE80211_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION 82
#define IEEE80211_STATUS_REFUSED_EXTERNAL_REASON 92
#define IEEE80211_STATUS_REFUSED_AP_OUT_OF_MEMORY 93
#define IEEE80211_STATUS_REJECTED_EMERGENCY_SERVICES_NOT_SUPPORTED 94
#define IEEE80211_STATUS_QUERY_RESPONSE_OUTSTANDING 95
#define IEEE80211_STATUS_MCCAOP_RESERVATION_CONFLICT 100
#define IEEE80211_STATUS_MAF_LIMIT_EXCEEDED 101
#define IEEE80211_STATUS_MCCA_TRACK_LIMIT_EXCEEDED 102
/* IEEE802.11 Reason code */
#define IEEE80211_REASON_UNSPECIFIED 1
#define IEEE80211_REASON_PREV_AUTH_NOT_VALID 2
#define IEEE80211_REASON_DEAUTH_LEAVING 3
#define IEEE80211_REASON_DISASSOC_DUE_TO_INACTIVITY 4
#define IEEE80211_REASON_DISASSOC_AP_BUSY 5
#define IEEE80211_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
#define IEEE80211_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
#define IEEE80211_REASON_DISASSOC_STA_HAS_LEFT 8
#define IEEE80211_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
#define IEEE80211_REASON_PWR_CAPABILITY_NOT_VALID 10
#define IEEE80211_REASON_SUPPORTED_CHANNEL_NOT_VALID 11
#define IEEE80211_REASON_INVALID_IE 13
#define IEEE80211_REASON_MICHAEL_MIC_FAILURE 14
#define IEEE80211_REASON_4WAY_HANDSHAKE_TIMEOUT 15
#define IEEE80211_REASON_GROUP_KEY_UPDATE_TIMEOUT 16
#define IEEE80211_REASON_IE_IN_4WAY_DIFFERS 17
#define IEEE80211_REASON_GROUP_CIPHER_NOT_VALID 18
#define IEEE80211_REASON_PAIRWISE_CIPHER_NOT_VALID 19
#define IEEE80211_REASON_AKMP_NOT_VALID 20
#define IEEE80211_REASON_UNSUPPORTED_RSN_IE_VERSION 21
#define IEEE80211_REASON_INVALID_RSN_IE_CAPAB 22
#define IEEE80211_REASON_IEEE_802_1X_AUTH_FAILED 23
#define IEEE80211_REASON_CIPHER_SUITE_REJECTED 24
#define IEEE80211_REASON_TDLS_TEARDOWN_UNREACHABLE 25
#define IEEE80211_REASON_TDLS_TEARDOWN_UNSPECIFIED 26
#define IEEE80211_REASON_DISASSOC_LOW_ACK 34
/* IEEE802.11 Authentication Algorithm */
#define IEEE80211_AUTHENTICATION_ALGORITHM_OPEN 0
#define IEEE80211_AUTHENTICATION_ALGORITHM_SHARED_KEY 1
#define IEEE80211_AUTHENTICATION_ALGORITHM_FAST_BSS 2
#define IEEE80211_AUTHENTICATION_ALGORITHM_SAE 3
/* */
#define IEEE80211_AID_FIELD 0xC000
#define IEEE80211_AID_MAX_VALUE 2007
/* */
#define IEEE80211_ERP_INFO_NON_ERP_PRESENT 0x01
#define IEEE80211_ERP_INFO_USE_PROTECTION 0x02
#define IEEE80211_ERP_INFO_BARKER_PREAMBLE_MODE 0x04
/* */
#define IEEE80211_CAPABILITY_ESS 0x0001
#define IEEE80211_CAPABILITY_IBSS 0x0002
#define IEEE80211_CAPABILITY_CFPOLLABLE 0x0004
#define IEEE80211_CAPABILITY_CFPOLLREQUEST 0x0008
#define IEEE80211_CAPABILITY_PRIVACY 0x0010
#define IEEE80211_CAPABILITY_SHORTPREAMBLE 0x0020
#define IEEE80211_CAPABILITY_PBCC 0x0040
#define IEEE80211_CAPABILITY_CHANNELAGILITY 0x0080
#define IEEE80211_CAPABILITY_SPECTRUMMAN 0x0100
#define IEEE80211_CAPABILITY_QOS 0x0200
#define IEEE80211_CAPABILITY_SHORTSLOTTIME 0x0400
#define IEEE80211_CAPABILITY_APSD 0x0800
#define IEEE80211_CAPABILITY_DSSS_OFDM 0x2000
#define IEEE80211_CAPABILITY_DELAYEDACK 0x4000
#define IEEE80211_CAPABILITY_IMMEDIATEACK 0x8000
/* 802.11 Packet - IEEE802.11 is a little-endian protocol */
struct ieee80211_header {
__le16 framecontrol;
__le16 durationid;
uint8_t address1[ETH_ALEN];
uint8_t address2[ETH_ALEN];
uint8_t address3[ETH_ALEN];
__le16 sequencecontrol;
} STRUCT_PACKED;
/* */
struct ieee80211_header_mgmt {
__le16 framecontrol;
__le16 durationid;
uint8_t da[ETH_ALEN];
uint8_t sa[ETH_ALEN];
uint8_t bssid[ETH_ALEN];
__le16 sequencecontrol;
union {
struct {
uint8_t timestamp[8];
__le16 beaconinterval;
__le16 capability;
uint8_t ie[0];
} STRUCT_PACKED beacon;
struct {
uint8_t ie[0];
} STRUCT_PACKED proberequest;
struct {
uint8_t timestamp[8];
__le16 beaconinterval;
__le16 capability;
uint8_t ie[0];
} STRUCT_PACKED proberesponse;
struct {
__le16 algorithm;
__le16 transactionseqnumber;
__le16 statuscode;
uint8_t ie[0];
} STRUCT_PACKED authetication;
struct {
__le16 capability;
__le16 listeninterval;
uint8_t ie[0];
} STRUCT_PACKED associationrequest;
struct {
__le16 capability;
__le16 statuscode;
__le16 aid;
uint8_t ie[0];
} STRUCT_PACKED associationresponse;
struct {
__le16 capability;
__le16 listeninterval;
uint8_t currentap[6];
uint8_t ie[0];
} STRUCT_PACKED reassociationrequest;
struct {
__le16 capability;
__le16 statuscode;
__le16 aid;
uint8_t ie[0];
} STRUCT_PACKED reassociationresponse;
struct {
__le16 reasoncode;
uint8_t ie[0];
} STRUCT_PACKED deauthetication;
struct {
__le16 reasoncode;
uint8_t ie[0];
} STRUCT_PACKED disassociation;
};
} STRUCT_PACKED;
/* 802.11 Generic information element */
struct ieee80211_ie {
uint8_t id;
uint8_t len;
} STRUCT_PACKED;
/* 802.11 SSID information element */
#define IEEE80211_IE_SSID 0
#define IEEE80211_IE_SSID_MAX_LENGTH 32
struct ieee80211_ie_ssid {
uint8_t id;
uint8_t len;
uint8_t ssid[0];
} STRUCT_PACKED;
/* 802.11 Supported Rates information element */
#define IEEE80211_IE_SUPPORTED_RATES 1
#define IEEE80211_IE_SUPPORTED_RATES_MIN_LENGTH 1
#define IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH 8
struct ieee80211_ie_supported_rates {
uint8_t id;
uint8_t len;
uint8_t rates[0];
} STRUCT_PACKED;
/* 802.11 DSSS information element */
#define IEEE80211_IE_DSSS 3
#define IEEE80211_IE_DSSS_LENGTH 1
struct ieee80211_ie_dsss {
uint8_t id;
uint8_t len;
uint8_t channel;
} STRUCT_PACKED;
/* 802.11 Country information element */
#define IEEE80211_IE_COUNTRY 7
#define IEEE80211_IE_COUNTRY_MIN_LENGTH 6
struct ieee80211_ie_country_channelgroup {
uint8_t firstchannel;
uint8_t numberchannels;
uint8_t maxtxpower;
} STRUCT_PACKED;
struct ieee80211_ie_country {
uint8_t id;
uint8_t len;
uint8_t country[3];
uint8_t channelgroup[0];
} STRUCT_PACKED;
/* 802.11 Challenge text information element */
#define IEEE80211_IE_CHALLENGE_TEXT 16
#define IEEE80211_IE_CHALLENGE_TEXT_MIN_LENGTH 3
struct ieee80211_ie_challenge_text {
uint8_t id;
uint8_t len;
uint8_t challengetext[0];
} STRUCT_PACKED;
/* 802.11 ERP information element */
#define IEEE80211_IE_ERP 42
#define IEEE80211_IE_ERP_LENGTH 1
struct ieee80211_ie_erp {
uint8_t id;
uint8_t len;
uint8_t params;
} STRUCT_PACKED;
/* 802.11 RSN information element */
#define IEEE80211_IE_RSN_INFORMATION 48
/* cipher suite selectors */
#define IEEE80211_CIPHER_SUITE_USE_GROUP 0x000FAC00
#define IEEE80211_CIPHER_SUITE_WEP40 0x000FAC01
#define IEEE80211_CIPHER_SUITE_TKIP 0x000FAC02
/* reserved: 0x000FAC03 */
#define IEEE80211_CIPHER_SUITE_CCMP 0x000FAC04
#define IEEE80211_CIPHER_SUITE_WEP104 0x000FAC05
#define IEEE80211_CIPHER_SUITE_AES_CMAC 0x000FAC06
#define IEEE80211_CIPHER_SUITE_NO_GROUP_ADDR 0x000FAC07
#define IEEE80211_CIPHER_SUITE_GCMP 0x000FAC08
#define IEEE80211_CIPHER_SUITE_GCMP_256 0x000FAC09
#define IEEE80211_CIPHER_SUITE_CCMP_256 0x000FAC0A
#define IEEE80211_CIPHER_SUITE_BIP_GMAC_128 0x000FAC0B
#define IEEE80211_CIPHER_SUITE_BIP_GMAC_256 0x000FAC0C
#define IEEE80211_CIPHER_SUITE_BIP_CMAC_256 0x000FAC0D
/* 802.11 Extended Supported Rates information element */
#define IEEE80211_IE_EXTENDED_SUPPORTED_RATES 50
#define IEEE80211_IE_EXTENDED_SUPPORTED_MIN_LENGTH 1
struct ieee80211_ie_extended_supported_rates {
uint8_t id;
uint8_t len;
uint8_t rates[0];
} STRUCT_PACKED;
/* 802.11 EDCA Parameter Set information element */
#define IEEE80211_IE_EDCA_PARAMETER_SET 12
#define IEEE80211_IE_EDCA_PARAMETER_SET_LENGTH 18
#define EDCA_PARAMETER_RECORD_AC_BE_FIELD 0
#define EDCA_PARAMETER_RECORD_AC_BK_FIELD 1
#define EDCA_PARAMETER_RECORD_AC_VI_FIELD 2
#define EDCA_PARAMETER_RECORD_AC_VO_FIELD 3
struct ieee80211_ie_edca_parameter_set {
uint8_t id;
uint8_t len;
/* TODO */
} STRUCT_PACKED;
/* 802.11 QoS Capability information element */
#define IEEE80211_IE_QOS_CAPABILITY 46
#define IEEE80211_IE_QOS_CAPABILITY_LENGTH 1
struct ieee80211_ie_qos_capability {
uint8_t id;
uint8_t len;
/* TODO */
} STRUCT_PACKED;
/* 802.11 Power Constraint information element */
#define IEEE80211_IE_POWER_CONSTRAINT 32
#define IEEE80211_IE_POWER_CONSTRAINT_LENGTH 1
struct ieee80211_ie_power_constraint {
uint8_t id;
uint8_t len;
/* TODO */
} STRUCT_PACKED;
/* 802.11 SSID List */
#define IEEE80211_IE_SSID_LIST 84
struct ieee80211_ie_ssid_list {
uint8_t id;
uint8_t len;
uint8_t lists[0];
} STRUCT_PACKED;
/* 802.11 Vendor Specific */
#define IEEE80211_IE_VENDOR_SPECIFIC 221
#define MICROSOFT_OUI 0x0050F2
struct ieee80211_ie_vendor_specific {
uint8_t id;
uint8_t len;
uint8_t oui[3];
uint8_t oui_type;
int8_t oui_subtype;
} STRUCT_PACKED;
#define WMM_TYPE 2
#define WMM_INFORMATION_ELEMENT 0
#define WMM_PARAMETER_ELEMENT 1
struct ieee80211_ie_wmm_information_element {
uint8_t id;
uint8_t len;
uint8_t oui[3];
uint8_t oui_type;
uint8_t oui_subtype;
uint8_t version;
uint8_t qos_info;
} STRUCT_PACKED;
#define IEEE80211_HT_MCS_MASK_LEN 10
struct ieee80211_mcs_info {
uint8_t rx_mask[IEEE80211_HT_MCS_MASK_LEN];
uint16_t rx_highest;
uint8_t tx_params;
uint8_t reserved[3];
} STRUCT_PACKED;
/**
* struct ieee80211_ht_cap - HT capabilities
*
* This structure is the "HT capabilities element" as
* described in 802.11n D5.0 7.3.2.57
*/
#define IEEE80211_IE_HT_CAPABILITY 45
struct ieee80211_ht_cap {
uint16_t cap_info;
uint8_t ampdu_params_info;
/* 16 bytes MCS information */
struct ieee80211_mcs_info mcs;
uint16_t extended_ht_cap_info;
uint32_t tx_BF_cap_info;
uint8_t antenna_selection_info;
} STRUCT_PACKED;
struct ieee80211_ie_ht_cap {
uint8_t id;
uint8_t len;
struct ieee80211_ht_cap ht_cap;
} STRUCT_PACKED;
/* 802.11n HT capabilities masks (for cap_info) */
#define IEEE80211_HT_CAP_LDPC_CODING 0x0001
#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002
#define IEEE80211_HT_CAP_SM_PS 0x000C
#define IEEE80211_HT_CAP_SM_PS_SHIFT 2
#define IEEE80211_HT_CAP_GRN_FLD 0x0010
#define IEEE80211_HT_CAP_SGI_20 0x0020
#define IEEE80211_HT_CAP_SGI_40 0x0040
#define IEEE80211_HT_CAP_TX_STBC 0x0080
#define IEEE80211_HT_CAP_RX_STBC 0x0300
#define IEEE80211_HT_CAP_RX_STBC_SHIFT 8
#define IEEE80211_HT_CAP_DELAY_BA 0x0400
#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800
#define IEEE80211_HT_CAP_DSSSCCK40 0x1000
#define IEEE80211_HT_CAP_RESERVED 0x2000
#define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000
#define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000
/**
* struct ieee80211_ht_operation - HT operation IE
*
* This structure is the "HT operation element" as
* described in 802.11n-2009 7.3.2.57
*/
#define IEEE80211_IE_HT_OPERATION 61
struct ieee80211_ht_operation {
uint8_t id;
uint8_t len;
uint8_t primary_chan;
uint8_t ht_param;
uint16_t operation_mode;
uint16_t stbc_param;
uint8_t basic_set[16];
} STRUCT_PACKED;
/* 802.11 All information elements */
struct ieee80211_ie_items {
struct ieee80211_ie_ssid *ssid;
struct ieee80211_ie_supported_rates *supported_rates;
struct ieee80211_ie_dsss *dsss;
struct ieee80211_ie_country *country;
struct ieee80211_ie_challenge_text *challenge_text;
struct ieee80211_ie_erp *erp;
struct ieee80211_ie_extended_supported_rates *extended_supported_rates;
struct ieee80211_ie_edca_parameter_set *edca_parameter_set;
struct ieee80211_ie_qos_capability *qos_capability;
struct ieee80211_ie_power_constraint *power_constraint;
struct ieee80211_ie_ssid_list *ssid_list;
struct ieee80211_ie_wmm_information_element *wmm_ie;
struct ieee80211_ie_ht_cap *ht_cap;
struct ieee80211_ht_operation *ht_oper;
};
/* IEEE 802.11 functions */
uint8_t ieee80211_get_erpinfo(uint32_t mode, int olbc, unsigned long stationnonerpcount, unsigned long stationnoshortpreamblecount, int shortpreamble);
/* Management Beacon */
#define IEEE80221_CREATE_BEACON_FLAGS_PROBE_RESPONSE_OFFLOAD 0x00000001
struct ieee80211_beacon_params {
unsigned long flags;
uint8_t* headbeacon;
int headbeaconlength;
uint8_t* tailbeacon;
int tailbeaconlength;
uint8_t bssid[ETH_ALEN];
uint16_t beaconperiod;
uint16_t capability;
const char* ssid;
int ssid_hidden;
int supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
uint8_t channel;
uint32_t mode;
uint8_t erpinfo;
int beacon_ies_len;
uint8_t *beacon_ies;
int response_ies_len;
uint8_t *response_ies;
uint8_t* proberesponseoffload;
int proberesponseoffloadlength;
};
int ieee80211_create_beacon(uint8_t* buffer, int length, struct ieee80211_beacon_params* params);
/* Management Probe Response */
struct ieee80211_probe_response_params {
uint8_t bssid[ETH_ALEN];
uint8_t station[ETH_ALEN];
uint16_t beaconperiod;
uint16_t capability;
const char* ssid;
int supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
uint8_t channel;
uint32_t mode;
uint8_t erpinfo;
int response_ies_len;
uint8_t *response_ies;
};
int ieee80211_create_probe_response(uint8_t* buffer, int length, struct ieee80211_probe_response_params* params);
/* Management Authentication */
struct ieee80211_authentication_params {
uint8_t bssid[ETH_ALEN];
uint8_t station[ETH_ALEN];
uint16_t algorithm;
uint16_t transactionseqnumber;
uint16_t statuscode;
};
int ieee80211_create_authentication_response(uint8_t* buffer, int length, struct ieee80211_authentication_params* params);
/* Management Association Response */
struct ieee80211_associationresponse_params {
uint8_t bssid[ETH_ALEN];
uint8_t station[ETH_ALEN];
uint16_t capability;
uint16_t statuscode;
uint16_t aid;
int supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
int response_ies_len;
uint8_t *response_ies;
};
int ieee80211_create_associationresponse_response(uint8_t* buffer, int length, struct ieee80211_associationresponse_params* params);
/* Management Deauthentication */
struct ieee80211_deauthentication_params {
uint8_t bssid[ETH_ALEN];
uint8_t station[ETH_ALEN];
uint16_t reasoncode;
};
int ieee80211_create_deauthentication(uint8_t* buffer, int length, struct ieee80211_deauthentication_params* params);
/* Management Disassociation */
struct ieee80211_disassociation_params {
uint8_t bssid[ETH_ALEN];
uint8_t station[ETH_ALEN];
uint16_t reasoncode;
};
int ieee80211_create_disassociation(uint8_t* buffer, int length, struct ieee80211_disassociation_params* params);
/* Utils */
int ieee80211_retrieve_information_elements_position(struct ieee80211_ie_items* items, const uint8_t* data, int length);
unsigned long ieee80211_frequency_to_channel(uint32_t freq);
int ieee80211_is_broadcast_addr(const uint8_t* addr);
/* */
const uint8_t* ieee80211_get_sa_addr(const struct ieee80211_header* header);
const uint8_t* ieee80211_get_da_addr(const struct ieee80211_header* header);
const uint8_t* ieee80211_get_bssid_addr(const struct ieee80211_header* header);
/* */
#define IEEE80211_VALID_SSID 1
#define IEEE80211_WILDCARD_SSID 0
#define IEEE80211_WRONG_SSID -1
int ieee80211_is_valid_ssid(const char* ssid, struct ieee80211_ie_ssid* iessid, struct ieee80211_ie_ssid_list* isssidlist);
/* IEEE802.11 Aid management */
#define IEEE80211_AID_BITFIELD_SIZE 63
int ieee80211_aid_create(uint32_t* aidbitfield, uint16_t* aid);
void ieee80211_aid_free(uint32_t* aidbitfield, uint16_t aid);
#endif /* __CAPWAP_IEEE802_11_HEADER__ */

93
lib/capwap.c Normal file
View File

@ -0,0 +1,93 @@
#include "capwap.h"
/* Helper exit */
void capwap_exit(int errorcode) {
exit(errorcode);
}
/* Init randon generator */
void capwap_init_rand(void) {
srand(time(NULL));
}
/* Get random number */
int capwap_get_rand(int max) {
if ((max < 0) || (max > RAND_MAX)) {
max = RAND_MAX;
}
return (rand() % max);
}
/* Duplicate string */
char* capwap_duplicate_string(const char* source) {
char* clone;
ASSERT(source != NULL);
clone = capwap_alloc(strlen(source) + 1);
strcpy(clone, source);
return clone;
}
/* Buffer clone */
void* capwap_clone(const void* buffer, int buffersize) {
void* bufferclone;
ASSERT(buffer != NULL);
ASSERT(buffersize > 0);
bufferclone = capwap_alloc(buffersize);
return memcpy(bufferclone, buffer, buffersize);
}
/* */
void capwap_daemon(void) {
int fd;
pid_t pid;
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
capwap_exit(CAPWAP_DAEMON_ERROR);
} else if (pid > 0) {
capwap_exit(CAPWAP_SUCCESSFUL);
}
/* Change the file mode mask */
umask(0);
/* Create a new SID for the child process */
if (setsid() < 0) {
capwap_exit(CAPWAP_DAEMON_ERROR);
}
/* Change the current working directory */
if ((chdir("/")) < 0) {
capwap_exit(CAPWAP_DAEMON_ERROR);
}
/* Redirect the standard file descriptors to /dev/null */
fd = open("/dev/null", 0);
if (fd == -1) {
capwap_exit(CAPWAP_DAEMON_ERROR);
}
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
close(fd);
}
/* */
char* capwap_itoa(int input, char* output) {
sprintf(output, "%d", input);
return output;
}
/* */
char* capwap_ltoa(long input, char* output) {
sprintf(output, "%ld", input);
return output;
}

90
lib/capwap.h Normal file
View File

@ -0,0 +1,90 @@
#ifndef __CAPWAP_HEADER__
#define __CAPWAP_HEADER__
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <poll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <sys/time.h>
#include <net/if.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* Endian */
#if __BYTE_ORDER == __BIG_ENDIAN
#define CAPWAP_BIG_ENDIAN
#else
#define CAPWAP_LITTLE_ENDIAN
#endif
/* Min & Max */
#ifndef max
#define max(a,b) ((a) >= (b) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) ((a) <= (b) ? (a) : (b))
#endif
/* Opaque type */
#define DECLARE_OPAQUE_TYPE(name) struct name##__opaque__ { int unused; }; typedef struct name##__opaque__* name
/* UDPLite */
#ifdef HAVE_NETINET_UDPLITE_H
#include <netinet/udplite.h>
#else
#ifndef IPPROTO_UDPLITE
#define IPPROTO_UDPLITE 136
#endif
#ifndef SOL_UDPLITE
#define SOL_UDPLITE 136
#endif
#ifndef UDPLITE_SEND_CSCOV
#define UDPLITE_SEND_CSCOV 10
#endif
#endif
/* standard include */
#include "rfc.h"
#include "logging.h"
#include "debug.h"
#include "error.h"
/* Helper exit */
void capwap_exit(int errorcode);
/* Random generator */
void capwap_init_rand(void);
int capwap_get_rand(int max);
/* */
void capwap_daemon(void);
/* */
#define capwap_outofmemory() do { \
log_printf(LOG_EMERG, "Out of memory %s(%d)", __FILE__, __LINE__); \
capwap_exit(CAPWAP_OUT_OF_MEMORY); \
} while(0)
/* Helper buffer copy */
char* capwap_duplicate_string(const char* source);
void* capwap_clone(const void* buffer, int buffersize);
/* */
char* capwap_itoa(int input, char* output);
char* capwap_ltoa(long input, char* output);
#endif /* __CAPWAP_HEADER__ */

29
lib/capwap_dfa.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef __CAPWAP_DFA_HEADER__
#define __CAPWAP_DFA_HEADER__
#define CAPWAP_UNDEF_STATE -1
#define CAPWAP_START_STATE 0
#define CAPWAP_IDLE_STATE 1
#define CAPWAP_DISCOVERY_STATE 2
#define CAPWAP_SULKING_STATE 3
#define CAPWAP_DTLS_CONNECT_STATE 4
#define CAPWAP_DTLS_TEARDOWN_STATE 5
#define CAPWAP_JOIN_STATE 6
#define CAPWAP_POSTJOIN_STATE 7
#define CAPWAP_IMAGE_DATA_STATE 8
#define CAPWAP_CONFIGURE_STATE 9
#define CAPWAP_RESET_STATE 10
#define CAPWAP_DATA_CHECK_STATE 11
#define CAPWAP_DATA_CHECK_TO_RUN_STATE 12
#define CAPWAP_RUN_STATE 13
#define CAPWAP_DEAD_STATE 14
#define CAPWAP_LAST_STATE 14
/* */
#ifdef DEBUG
char* capwap_dfa_getname(int state);
#else
#define capwap_dfa_getname(x) ""
#endif
#endif /* __CAPWAP_DFA_HEADER__ */

178
lib/debug.c Normal file
View File

@ -0,0 +1,178 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef USE_DEBUG_BACKTRACE
#include <execinfo.h>
#endif
#include "logging.h"
#include "error.h"
#define BACKTRACE_BUFFER 256
/* Memory block */
struct capwap_memory_block {
void* item;
size_t size;
const char* file;
int line;
#ifdef USE_DEBUG_BACKTRACE
void* backtrace[BACKTRACE_BUFFER];
int backtrace_count;
#endif
struct capwap_memory_block* next;
};
static struct capwap_memory_block* g_memoryblocks = NULL;
/* Alloc memory block */
void* capwap_alloc_debug(size_t size, const char* file, const int line) {
struct capwap_memory_block* block;
/* Request size > 0 */
if (size <= 0) {
log_printf(LOG_DEBUG, "%s(%d): Invalid memory size %zu", file, line, size);
exit(CAPWAP_ASSERT_CONDITION);
}
/* Alloc block with memory block */
block = (struct capwap_memory_block*)malloc(sizeof(struct capwap_memory_block) + size);
if (!block) {
log_printf(LOG_DEBUG, "Out of memory %s(%d)", file, line);
exit(CAPWAP_OUT_OF_MEMORY);
}
/* Info memory block */
block->item = (void*)(((char*)block) + sizeof(struct capwap_memory_block));
block->size = size;
block->file = file;
block->line = line;
#ifdef USE_DEBUG_BACKTRACE
block->backtrace_count = backtrace(block->backtrace, BACKTRACE_BUFFER);
#endif
block->next = g_memoryblocks;
g_memoryblocks = block;
return block->item;
}
/* Free memory block */
void capwap_free_debug(void* p, const char* file, const int line) {
struct capwap_memory_block* block;
struct capwap_memory_block* findblock;
struct capwap_memory_block* prevblock;
if (!p) {
log_printf(LOG_DEBUG, "%s(%d): Free NULL pointer", file, line);
exit(CAPWAP_ASSERT_CONDITION);
}
/* Memory block */
if ((size_t)p <= sizeof(struct capwap_memory_block)) {
log_printf(LOG_DEBUG, "%s(%d): Invalid pointer", file, line);
exit(CAPWAP_ASSERT_CONDITION);
}
block = (struct capwap_memory_block*)((char*)p - sizeof(struct capwap_memory_block));
if (block->item != p) {
log_printf(LOG_DEBUG, "%s(%d): Invalid pointer", file, line);
exit(CAPWAP_ASSERT_CONDITION);
}
/* Find memory block */
prevblock = NULL;
findblock = g_memoryblocks;
while (findblock != NULL) {
if (findblock == block) {
if (!prevblock) {
g_memoryblocks = block->next;
} else {
prevblock->next = block->next;
}
/* Invalidate block */
memset(block, 0, sizeof(struct capwap_memory_block));
free(block);
return;
}
/* Next */
prevblock = findblock;
findblock = findblock->next;
}
log_printf(LOG_DEBUG, "%s(%d): Unable to find memory block", file, line);
}
/* Dump memory alloced */
void capwap_dump_memory(void) {
#ifdef USE_DEBUG_BACKTRACE
char** backtrace_functions;
#endif
struct capwap_memory_block* findblock;
findblock = g_memoryblocks;
while (findblock != NULL) {
log_printf(LOG_DEBUG, "%s(%d): block at %p, %zu bytes long",
findblock->file, findblock->line, findblock->item, findblock->size);
#ifdef USE_DEBUG_BACKTRACE
backtrace_functions = backtrace_symbols(findblock->backtrace, findblock->backtrace_count);
if (backtrace_functions) {
int j;
/* Skipping capwap_alloc_debug function print out */
for (j = 1; j < findblock->backtrace_count; j++) {
log_printf(LOG_DEBUG, "\t%s", backtrace_functions[j]);
}
free(backtrace_functions);
}
#endif
/* Next */
findblock = findblock->next;
}
}
/* Check if all memory is free */
int capwap_check_memory_leak(int verbose) {
if ((g_memoryblocks != NULL) && (verbose != 0)) {
log_printf(LOG_DEBUG, "*** Detected memory leaks ! ***");
capwap_dump_memory();
log_printf(LOG_DEBUG, "*******************************");
}
return ((g_memoryblocks != NULL) ? 1 : 0);
}
/* Backtrace call stack */
#ifdef USE_DEBUG_BACKTRACE
void capwap_backtrace_callstack(void) {
int i;
int count;
char** functions;
void* buffer[BACKTRACE_BUFFER];
/* */
count = backtrace(buffer, BACKTRACE_BUFFER);
if (count) {
functions = backtrace_symbols(buffer, count);
if (functions) {
/* Skipping capwap_backtrace_callstack function print out */
for (i = 1; i < count; i++) {
log_printf(LOG_DEBUG, "\t%s", functions[i]);
}
free(functions);
}
}
}
#endif

39
lib/debug.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef __CAPWAP_DEBUG_HEADER__
#define __CAPWAP_DEBUG_HEADER__
#ifdef DEBUG
#define ASSERT(expr) if (!(expr)) { log_printf(LOG_EMERG, "Assertion failed \'%s\': %s(%d)", #expr, __FILE__, __LINE__); capwap_exit(CAPWAP_ASSERT_CONDITION); }
/* Custom memory management */
#define capwap_alloc(x) capwap_alloc_debug(x, __FILE__, __LINE__)
void* capwap_alloc_debug(size_t size, const char* file, const int line);
#define capwap_free(x) capwap_free_debug(x, __FILE__, __LINE__)
void capwap_free_debug(void* p, const char* file, const int line);
int capwap_check_memory_leak(int verbose);
void capwap_dump_memory(void);
#ifdef USE_DEBUG_BACKTRACE
void capwap_backtrace_callstack(void);
#else
#define capwap_backtrace_callstack()
#endif
#else
#define DEBUG_BREAKPOINT()
#define ASSERT(expr)
/* Standard memory management */
#define capwap_alloc(l) ({ void* __x = malloc(l); if (!__x) capwap_outofmemory(); __x; })
#define capwap_free(x) free(x)
#define capwap_check_memory_leak(x) (0)
#define capwap_dump_memory()
#define capwap_backtrace_callstack()
#endif
#endif /* __CAPWAP_DEBUG_HEADER__ */

33
lib/dfa.c Normal file
View File

@ -0,0 +1,33 @@
#include "capwap.h"
#include "capwap_dfa.h"
#ifdef DEBUG
static char* l_nameofstate[] = {
"START", /* CAPWAP_START_STATE */
"IDLE", /* CAPWAP_IDLE_STATE */
"DISCOVERY", /* CAPWAP_DISCOVERY_STATE */
"SULKING", /* CAPWAP_SULKING_STATE */
"DTLS_CONNECT", /* CAPWAP_DTLS_CONNECT_STATE */
"DTLS_TEARDOWN", /* CAPWAP_DTLS_TEARDOWN_STATE */
"JOIN", /* CAPWAP_JOIN_STATE */
"POST_JOIN", /* CAPWAP_POSTJOIN_STATE */
"IMAGE_DATA", /* CAPWAP_IMAGE_DATA_STATE */
"CONFIGURE", /* CAPWAP_CONFIGURE_STATE */
"RESET", /* CAPWAP_RESET_STATE */
"DATA_CHECK", /* CAPWAP_DATA_CHECK_STATE */
"DATA_CHECK_TO_RUN", /* CAPWAP_DATA_CHECK_TO_RUN_STATE */
"RUN", /* CAPWAP_RUN_STATE */
"DEAD" /* CAPWAP_DEAD_STATE */
};
/* */
char* capwap_dfa_getname(int state) {
if ((state < 0) || (state > CAPWAP_LAST_STATE)) {
return "";
}
return l_nameofstate[state];
}
#endif

634
lib/dtls.c Normal file
View File

@ -0,0 +1,634 @@
#include "capwap.h"
#include "dtls.h"
#include "protocol.h"
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/sha.h>
/* */
static const char g_char2hex[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
-1, -1, -1, -1, -1, -1, -1,
10, 11, 12, 13, 14, 15, /* Upper Case A - F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10, 11, 12, 13, 14, 15 /* Lower Case a - f */
};
static const int g_char2hex_length = sizeof(g_char2hex) / sizeof(g_char2hex[0]);
/* */
static int capwap_bio_method_recv(WOLFSSL* ssl, char* buffer, int length, void* context) {
struct capwap_dtls* dtls = (struct capwap_dtls*)context;
struct capwap_dtls_header* dtlspreamble;
int size;
/* Check read packet */
if ((dtls->length < sizeof(struct capwap_dtls_header)) || !dtls->buffer) {
if (!dtls->length && !dtls->buffer) {
return WOLFSSL_CBIO_ERR_WANT_READ; /* Notify empty buffer */
}
return WOLFSSL_CBIO_ERR_GENERAL;
}
/* Check DTLS Capwap Preamble */
dtlspreamble = (struct capwap_dtls_header*)dtls->buffer;
if ((dtlspreamble->preamble.version != CAPWAP_PROTOCOL_VERSION) || (dtlspreamble->preamble.type != CAPWAP_PREAMBLE_DTLS_HEADER)) {
log_printf(LOG_DEBUG, "Wrong DTLS Capwap Preamble");
return WOLFSSL_CBIO_ERR_GENERAL; /* Wrong DTLS Capwap Preamble */
}
/* */
size = dtls->length - sizeof(struct capwap_dtls_header);
dtls->length = 0;
dtls->buffer += sizeof(struct capwap_dtls_header);
if (size > length) {
dtls->buffer = NULL;
return WOLFSSL_CBIO_ERR_GENERAL;
}
/* Copy DTLS packet */
memcpy(buffer, dtls->buffer, size);
dtls->buffer = NULL;
return size;
}
/* */
static int capwap_bio_method_send(WOLFSSL* ssl, char* buffer, int length, void* context) {
int err;
char data[CAPWAP_MAX_PACKET_SIZE];
struct capwap_dtls* dtls = (struct capwap_dtls*)context;
struct capwap_dtls_header* dtlspreamble = (struct capwap_dtls_header*)data;
/* Check for maxium size of packet */
if (length > (CAPWAP_MAX_PACKET_SIZE - sizeof(struct capwap_dtls_header))) {
return WOLFSSL_CBIO_ERR_GENERAL;
}
/* Create DTLS Capwap Preamble */
dtlspreamble->preamble.version = CAPWAP_PROTOCOL_VERSION;
dtlspreamble->preamble.type = CAPWAP_PREAMBLE_DTLS_HEADER;
dtlspreamble->reserved1 = dtlspreamble->reserved2 = dtlspreamble->reserved3 = 0;
memcpy(&data[0] + sizeof(struct capwap_dtls_header), buffer, length);
/* Send packet */
err = capwap_sendto(dtls->sock, data, length + sizeof(struct capwap_dtls_header), &dtls->peeraddr);
if (err <= 0) {
log_printf(LOG_WARNING, "Unable to send crypt packet, sentto return error %d", err);
return WOLFSSL_CBIO_ERR_GENERAL;
}
/* Don't return size of DTLS Capwap Preamble */
return length;
}
/* */
int capwap_crypt_init() {
int result;
/* Init library */
result = wolfSSL_Init();
if (result != SSL_SUCCESS) {
return -1;
}
return 0;
}
/* */
void capwap_crypt_free() {
wolfSSL_Cleanup();
}
/* */
static int capwap_crypt_verifycertificate(int preverify_ok, WOLFSSL_X509_STORE_CTX* ctx) {
return preverify_ok;
}
/* */
static unsigned int capwap_crypt_psk_client(WOLFSSL* ssl, const char* hint, char* identity, unsigned int max_identity_len, unsigned char* psk, unsigned int max_psk_len) {
struct capwap_dtls* dtls = (struct capwap_dtls*)wolfSSL_GetIOReadCtx(ssl);
ASSERT(dtls != NULL);
ASSERT(dtls->dtlscontext != NULL);
/* */
if ((max_identity_len < strlen(dtls->dtlscontext->presharedkey.identity)) || (max_psk_len < dtls->dtlscontext->presharedkey.pskkeylength)) {
return 0;
}
/* */
strcpy(identity, dtls->dtlscontext->presharedkey.identity);
memcpy(psk, dtls->dtlscontext->presharedkey.pskkey, dtls->dtlscontext->presharedkey.pskkeylength);
return dtls->dtlscontext->presharedkey.pskkeylength;
}
/* */
static unsigned int capwap_crypt_psk_server(WOLFSSL* ssl, const char* identity, unsigned char* psk, unsigned int max_psk_len) {
struct capwap_dtls* dtls = (struct capwap_dtls*)wolfSSL_GetIOReadCtx(ssl);
ASSERT(dtls != NULL);
ASSERT(dtls->dtlscontext != NULL);
/* */
if (strcmp(identity, dtls->dtlscontext->presharedkey.identity) || (max_psk_len < dtls->dtlscontext->presharedkey.pskkeylength)) {
return 0;
}
/* */
memcpy(psk, dtls->dtlscontext->presharedkey.pskkey, dtls->dtlscontext->presharedkey.pskkeylength);
return dtls->dtlscontext->presharedkey.pskkeylength;
}
/* */
static unsigned int capwap_crypt_psk_to_bin(char* pskkey, unsigned char** pskbin) {
int i, j;
int length;
int result;
unsigned char* buffer;
/* Convert string to hex */
length = strlen(pskkey);
if (!length || (length % 2)) {
return 0;
}
/* */
result = length / 2;
buffer = (unsigned char*)capwap_alloc(result);
for (i = 0, j = 0; i < length; i += 2, j++) {
char valuehi = pskkey[i] - 48;
char valuelo = pskkey[i + 1] - 48;
/* Check value */
if ((valuehi < 0) || (valuehi >= g_char2hex_length) || (valuelo < 0) || (valuelo >= g_char2hex_length)) {
capwap_free(buffer);
return 0;
}
/* */
valuehi = g_char2hex[(int)valuehi];
valuelo = g_char2hex[(int)valuelo];
/* Check value */
if ((valuehi < 0) || (valuelo < 0)) {
capwap_free(buffer);
return 0;
}
/* */
buffer[j] = (unsigned char)(((unsigned char)valuehi << 4) | (unsigned char)valuelo);
}
/* */
*pskbin = buffer;
return result;
}
/* */
static int capwap_crypt_createcookie(WOLFSSL* ssl, unsigned char* buffer, int size, void* context) {
int length;
unsigned char temp[32];
Sha sha;
byte digest[SHA_DIGEST_SIZE];
struct capwap_dtls* dtls = (struct capwap_dtls*)context;
if (size != SHA_DIGEST_SIZE) {
return -1;
}
/* Create buffer with peer's address and port */
if (dtls->peeraddr.ss.ss_family == AF_INET) {
length = sizeof(struct in_addr) + sizeof(in_port_t);
memcpy(temp, &dtls->peeraddr.sin.sin_port, sizeof(in_port_t));
memcpy(temp + sizeof(in_port_t), &dtls->peeraddr.sin.sin_addr, sizeof(struct in_addr));
} else if (dtls->peeraddr.ss.ss_family == AF_INET6) {
length = sizeof(struct in6_addr) + sizeof(in_port_t);
memcpy(temp, &dtls->peeraddr.sin6.sin6_port, sizeof(in_port_t));
memcpy(temp + sizeof(in_port_t), &dtls->peeraddr.sin6.sin6_addr, sizeof(struct in6_addr));
} else {
return -1;
}
/* */
if (wc_InitSha(&sha)) {
return -1;
}
wc_ShaUpdate(&sha, temp, length);
wc_ShaFinal(&sha, digest);
/* */
memcpy(buffer, digest, SHA_DIGEST_SIZE);
return SHA_DIGEST_SIZE;
}
/* */
int capwap_crypt_createcontext(struct capwap_dtls_context* dtlscontext, struct capwap_dtls_param* param) {
ASSERT(dtlscontext != NULL);
ASSERT(param != NULL);
memset(dtlscontext, 0, sizeof(struct capwap_dtls_context));
dtlscontext->type = param->type;
dtlscontext->mode = param->mode;
/* Alloc context */
dtlscontext->sslcontext = (void*)wolfSSL_CTX_new(((param->type == CAPWAP_DTLS_SERVER) ? wolfDTLSv1_server_method() : wolfDTLSv1_client_method()));
if (!dtlscontext->sslcontext) {
log_printf(LOG_DEBUG, "Error to initialize dtls context");
return 0;
}
/* Set context IO */
wolfSSL_SetIORecv((WOLFSSL_CTX*)dtlscontext->sslcontext, capwap_bio_method_recv);
wolfSSL_SetIOSend((WOLFSSL_CTX*)dtlscontext->sslcontext, capwap_bio_method_send);
wolfSSL_CTX_SetGenCookie((WOLFSSL_CTX*)dtlscontext->sslcontext, capwap_crypt_createcookie);
/* */
if (dtlscontext->mode == CAPWAP_DTLS_MODE_CERTIFICATE) {
/* Check context */
if (!param->cert.filecert || !strlen(param->cert.filecert)) {
log_printf(LOG_DEBUG, "Error, request certificate file");
capwap_crypt_freecontext(dtlscontext);
return 0;
} else if (!param->cert.filekey || !strlen(param->cert.filekey)) {
log_printf(LOG_DEBUG, "Error, request privatekey file");
capwap_crypt_freecontext(dtlscontext);
return 0;
} else if (!param->cert.fileca || !strlen(param->cert.fileca)) {
log_printf(LOG_DEBUG, "Error, request ca file");
capwap_crypt_freecontext(dtlscontext);
return 0;
}
/* Public certificate */
if (!wolfSSL_CTX_use_certificate_file((WOLFSSL_CTX*)dtlscontext->sslcontext, param->cert.filecert, SSL_FILETYPE_PEM)) {
log_printf(LOG_DEBUG, "Error to load certificate file");
capwap_crypt_freecontext(dtlscontext);
return 0;
}
/* Private key */
if (!wolfSSL_CTX_use_PrivateKey_file((WOLFSSL_CTX*)dtlscontext->sslcontext, param->cert.filekey, SSL_FILETYPE_PEM)) {
log_printf(LOG_DEBUG, "Error to load private key file");
capwap_crypt_freecontext(dtlscontext);
return 0;
}
if (!wolfSSL_CTX_check_private_key((WOLFSSL_CTX*)dtlscontext->sslcontext)) {
log_printf(LOG_DEBUG, "Error to check private key");
capwap_crypt_freecontext(dtlscontext);
return 0;
}
/* Certificate Authority */
if (!wolfSSL_CTX_load_verify_locations((WOLFSSL_CTX*)dtlscontext->sslcontext, param->cert.fileca, NULL)) {
log_printf(LOG_DEBUG, "Error to load ca file");
capwap_crypt_freecontext(dtlscontext);
return 0;
}
/* Verify certificate callback */
wolfSSL_CTX_set_verify((WOLFSSL_CTX*)dtlscontext->sslcontext, ((param->type == CAPWAP_DTLS_SERVER) ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_PEER), capwap_crypt_verifycertificate);
/* Cipher list:
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_DHE_RSA_WITH_AES_256_CBC_SHA
*/
if (!wolfSSL_CTX_set_cipher_list((WOLFSSL_CTX*)dtlscontext->sslcontext, "AES128-SHA:DHE-RSA-AES128-SHA:AES256-SHA:DHE-RSA-AES256-SHA")) {
log_printf(LOG_DEBUG, "Error to select cipher list");
capwap_crypt_freecontext(dtlscontext);
return 0;
}
} else if (dtlscontext->mode == CAPWAP_DTLS_MODE_PRESHAREDKEY) {
/* Cipher list:
TLS_PSK_WITH_AES_128_CBC_SHA
TLS_DHE_PSK_WITH_AES_128_CBC_SHA
TLS_PSK_WITH_AES_256_CBC_SHA
TLS_DHE_PSK_WITH_AES_256_CBC_SHA
*/
if (!wolfSSL_CTX_set_cipher_list((WOLFSSL_CTX*)dtlscontext->sslcontext, "PSK-AES128-CBC-SHA:PSK-AES256-CBC-SHA")) {
log_printf(LOG_DEBUG, "Error to select cipher list");
capwap_crypt_freecontext(dtlscontext);
return 0;
}
/* */
if (dtlscontext->type == CAPWAP_DTLS_SERVER) {
if (param->presharedkey.hint) {
wolfSSL_CTX_use_psk_identity_hint((WOLFSSL_CTX*)dtlscontext->sslcontext, param->presharedkey.hint);
} else {
log_printf(LOG_DEBUG, "Error to presharedkey hint");
capwap_crypt_freecontext(dtlscontext);
return 0;
}
}
/* */
dtlscontext->presharedkey.identity = capwap_duplicate_string(param->presharedkey.identity);
dtlscontext->presharedkey.pskkeylength = capwap_crypt_psk_to_bin(param->presharedkey.pskkey, &dtlscontext->presharedkey.pskkey);
if (!dtlscontext->presharedkey.pskkeylength) {
log_printf(LOG_DEBUG, "Error to presharedkey");
capwap_crypt_freecontext(dtlscontext);
return 0;
}
/* */
if (dtlscontext->type == CAPWAP_DTLS_SERVER) {
wolfSSL_CTX_set_psk_server_callback((WOLFSSL_CTX*)dtlscontext->sslcontext, capwap_crypt_psk_server);
} else {
wolfSSL_CTX_set_psk_client_callback((WOLFSSL_CTX*)dtlscontext->sslcontext, capwap_crypt_psk_client);
}
} else {
log_printf(LOG_DEBUG, "Invalid DTLS mode");
capwap_crypt_freecontext(dtlscontext);
return 0;
}
return 1;
}
/* */
void capwap_crypt_freecontext(struct capwap_dtls_context* dtlscontext) {
ASSERT(dtlscontext != NULL);
/* */
if (dtlscontext->mode == CAPWAP_DTLS_MODE_PRESHAREDKEY) {
if (dtlscontext->presharedkey.identity) {
capwap_free(dtlscontext->presharedkey.identity);
}
if (dtlscontext->presharedkey.pskkey) {
capwap_free(dtlscontext->presharedkey.pskkey);
}
}
/* Free context */
if (dtlscontext->sslcontext) {
wolfSSL_CTX_free((WOLFSSL_CTX*)dtlscontext->sslcontext);
}
memset(dtlscontext, 0, sizeof(struct capwap_dtls_context));
}
/* */
int capwap_crypt_createsession(struct capwap_dtls* dtls, struct capwap_dtls_context* dtlscontext) {
ASSERT(dtls != NULL);
ASSERT(dtlscontext != NULL);
ASSERT(dtlscontext->sslcontext != NULL);
/* Create ssl session */
dtls->sslsession = (void*)wolfSSL_new((WOLFSSL_CTX*)dtlscontext->sslcontext);
if (!dtls->sslsession) {
log_printf(LOG_DEBUG, "Error to initialize dtls session");
return 0;
}
/* */
wolfSSL_set_using_nonblock((WOLFSSL*)dtls->sslsession, 1);
wolfSSL_SetIOReadCtx((WOLFSSL*)dtls->sslsession, (void*)dtls);
wolfSSL_SetIOWriteCtx((WOLFSSL*)dtls->sslsession, (void*)dtls);
wolfSSL_SetCookieCtx((WOLFSSL*)dtls->sslsession, (void*)dtls);
/* */
dtls->action = CAPWAP_DTLS_ACTION_NONE;
dtls->dtlscontext = dtlscontext;
dtls->enable = 1;
dtls->buffer = NULL;
dtls->length = 0;
return 1;
}
/* */
static int capwap_crypt_handshake(struct capwap_dtls* dtls) {
int result;
ASSERT(dtls != NULL);
ASSERT(dtls->enable != 0);
ASSERT((dtls->action == CAPWAP_DTLS_ACTION_NONE) || (dtls->action == CAPWAP_DTLS_ACTION_HANDSHAKE));
/* */
if (dtls->dtlscontext->type == CAPWAP_DTLS_SERVER) {
result = wolfSSL_accept((WOLFSSL*)dtls->sslsession);
} else {
result = wolfSSL_connect((WOLFSSL*)dtls->sslsession);
}
/* */
if (result != SSL_SUCCESS) {
char buffer[WOLFSSL_MAX_ERROR_SZ];
result = wolfSSL_get_error((WOLFSSL*)dtls->sslsession, 0);
if ((result == SSL_ERROR_WANT_READ) || (result == SSL_ERROR_WANT_WRITE)) {
/* Incomplete handshake */
dtls->action = CAPWAP_DTLS_ACTION_HANDSHAKE;
return CAPWAP_HANDSHAKE_CONTINUE;
}
log_printf(LOG_DEBUG, "Error in DTLS handshake: %s",
wolfSSL_ERR_error_string(result, buffer));
/* Handshake error */
dtls->action = CAPWAP_DTLS_ACTION_ERROR;
return CAPWAP_HANDSHAKE_ERROR;
}
/* Handshake complete */
dtls->action = CAPWAP_DTLS_ACTION_DATA;
return CAPWAP_HANDSHAKE_COMPLETE;
}
/* */
void capwap_crypt_setconnection(struct capwap_dtls* dtls, int sock, union sockaddr_capwap* localaddr, union sockaddr_capwap* peeraddr) {
ASSERT(sock >= 0);
ASSERT(localaddr != NULL);
ASSERT(peeraddr != NULL);
dtls->sock = sock;
/* */
memcpy(&dtls->localaddr, localaddr, sizeof(union sockaddr_capwap));
if (dtls->localaddr.ss.ss_family == AF_INET6) {
capwap_ipv4_mapped_ipv6(&dtls->localaddr);
}
/* */
memcpy(&dtls->peeraddr, peeraddr, sizeof(union sockaddr_capwap));
if (dtls->peeraddr.ss.ss_family == AF_INET6) {
capwap_ipv4_mapped_ipv6(&dtls->peeraddr);
}
}
/* */
int capwap_crypt_open(struct capwap_dtls* dtls) {
return capwap_crypt_handshake(dtls);
}
/* */
void capwap_crypt_close(struct capwap_dtls* dtls) {
ASSERT(dtls != NULL);
ASSERT(dtls->enable != 0);
if (dtls->sslsession) {
wolfSSL_shutdown((WOLFSSL*)dtls->sslsession);
}
}
/* */
void capwap_crypt_freesession(struct capwap_dtls* dtls) {
ASSERT(dtls != NULL);
/* Free SSL session */
if (dtls->sslsession) {
wolfSSL_free((WOLFSSL*)dtls->sslsession);
}
/* */
memset(dtls, 0, sizeof(struct capwap_dtls));
}
/* */
int capwap_crypt_sendto(struct capwap_dtls* dtls, void* buffer, int size) {
int err;
ASSERT(dtls != NULL);
ASSERT(dtls->sock >= 0);
ASSERT(buffer != NULL);
ASSERT(size > 0);
if (!dtls->enable) {
err = capwap_sendto(dtls->sock, buffer, size, &dtls->peeraddr);
if (err <= 0) {
log_printf(LOG_WARNING, "Unable to send plain packet, sentto return error %d", err);
}
return err;
}
/* Valid DTLS status */
if (dtls->action != CAPWAP_DTLS_ACTION_DATA) {
return -ENOTCONN;
}
return wolfSSL_write((WOLFSSL*)dtls->sslsession, buffer, size);
}
/* */
int capwap_crypt_sendto_fragmentpacket(struct capwap_dtls* dtls, struct capwap_list* fragmentlist) {
int err;
struct capwap_list_item* item;
ASSERT(dtls != NULL);
ASSERT(dtls->sock >= 0);
ASSERT(fragmentlist != NULL);
/* */
if (!dtls->enable) {
return capwap_sendto_fragmentpacket(dtls->sock, fragmentlist, &dtls->peeraddr);
}
/* */
item = fragmentlist->first;
while (item) {
struct capwap_fragment_packet_item* fragmentpacket = (struct capwap_fragment_packet_item*)item->item;
ASSERT(fragmentpacket != NULL);
ASSERT(fragmentpacket->offset > 0);
err = capwap_crypt_sendto(dtls, fragmentpacket->buffer, fragmentpacket->offset);
if (err <= 0) {
log_printf(LOG_WARNING, "Unable to send crypt fragment, sentto return error %d", err);
return 0;
}
/* */
item = item->next;
}
return 1;
}
/* */
int capwap_decrypt_packet(struct capwap_dtls* dtls, void* encrybuffer, int size, void* plainbuffer, int maxsize) {
int sslerror;
int result = -1;
char* clone = NULL;
ASSERT(dtls != NULL);
ASSERT(dtls->enable != 0);
ASSERT((dtls->action == CAPWAP_DTLS_ACTION_HANDSHAKE) || (dtls->action == CAPWAP_DTLS_ACTION_DATA));
ASSERT(dtls->buffer == NULL);
ASSERT(dtls->length == 0);
ASSERT(encrybuffer != NULL);
ASSERT(size > 0);
ASSERT(maxsize > 0);
/* */
if (!plainbuffer) {
clone = capwap_clone(encrybuffer, size);
}
dtls->buffer = (clone ? clone : encrybuffer);
dtls->length = size;
/* */
if (dtls->action == CAPWAP_DTLS_ACTION_HANDSHAKE) {
if (capwap_crypt_handshake(dtls) == CAPWAP_HANDSHAKE_ERROR) {
result = CAPWAP_ERROR_CLOSE; /* Error handshake */
} else {
result = CAPWAP_ERROR_AGAIN; /* Don't parsing DTLS packet */
}
} else if (dtls->action == CAPWAP_DTLS_ACTION_DATA) {
result = wolfSSL_read((WOLFSSL*)dtls->sslsession, (plainbuffer ? plainbuffer : encrybuffer), maxsize);
if (!result) {
dtls->action = CAPWAP_DTLS_ACTION_SHUTDOWN;
result = CAPWAP_ERROR_SHUTDOWN;
} else if (result < 0) {
/* Check error */
sslerror = wolfSSL_get_error((WOLFSSL*)dtls->sslsession, 0);
if ((sslerror == SSL_ERROR_WANT_READ) || (sslerror == SSL_ERROR_WANT_WRITE)) {
result = CAPWAP_ERROR_AGAIN; /* DTLS Renegotiation */
} else {
result = CAPWAP_ERROR_CLOSE;
}
}
}
/* Verify BIO read */
ASSERT(dtls->buffer == NULL);
ASSERT(dtls->length == 0);
/* Free clone */
if (clone) {
capwap_free(clone);
}
return result;
}
/* */
#define SIZEOF_DTLS_LAYERS 14
#define DTLS_RECORD_LAYER_HANDSHAKE_CONTENT_TYPE 22
#define DTLS_1_0_VERSION 0xfeff
#define DTLS_1_2_VERSION 0xfefd
#define DTLS_HANDSHAKE_LAYER_CLIENT_HELLO 1
/* */
int capwap_crypt_has_dtls_clienthello(void* buffer, int buffersize) {
unsigned char* dtlsdata = (unsigned char*)buffer;
/* Read DTLS packet in RAW mode */
if ((buffer != NULL) && (buffersize > SIZEOF_DTLS_LAYERS)) {
if (dtlsdata[0] == DTLS_RECORD_LAYER_HANDSHAKE_CONTENT_TYPE) {
uint16_t version = ntohs(*(uint16_t*)(dtlsdata + 1));
if (((version == DTLS_1_0_VERSION) || (version == DTLS_1_2_VERSION)) && (dtlsdata[13] == DTLS_HANDSHAKE_LAYER_CLIENT_HELLO)) {
return 1;
}
}
}
return 0;
}

107
lib/dtls.h Normal file
View File

@ -0,0 +1,107 @@
#ifndef __CAPWAP_DTLS_HEADER__
#define __CAPWAP_DTLS_HEADER__
#include "list.h"
#include "network.h"
#define CAPWAP_DTLS_CLIENT 0
#define CAPWAP_DTLS_SERVER 1
#define CAPWAP_DTLS_MODE_NONE 0
#define CAPWAP_DTLS_MODE_CERTIFICATE 1
#define CAPWAP_DTLS_MODE_PRESHAREDKEY 2
#define CAPWAP_DTLS_ACTION_NONE 0
#define CAPWAP_DTLS_ACTION_HANDSHAKE 1
#define CAPWAP_DTLS_ACTION_DATA 2
#define CAPWAP_DTLS_ACTION_SHUTDOWN 3
#define CAPWAP_DTLS_ACTION_ERROR 4
#define CAPWAP_HANDSHAKE_ERROR -1
#define CAPWAP_HANDSHAKE_CONTINUE 0
#define CAPWAP_HANDSHAKE_COMPLETE 1
#define CAPWAP_ERROR_AGAIN 0
#define CAPWAP_ERROR_SHUTDOWN -1
#define CAPWAP_ERROR_CLOSE -2
/* */
struct capwap_dtls;
/* */
struct capwap_dtls_context {
int type;
int mode;
void* sslcontext;
union {
struct {
char* identity;
unsigned char* pskkey;
unsigned int pskkeylength;
} presharedkey;
};
};
/* */
struct capwap_dtls {
int enable;
int action;
/* */
void* sslsession;
struct capwap_dtls_context* dtlscontext;
/* */
int sock;
union sockaddr_capwap localaddr;
union sockaddr_capwap peeraddr;
/* Buffer read */
void* buffer;
int length;
};
/* */
struct capwap_dtls_param {
int type;
int mode;
union {
struct {
char* hint;
char* identity;
char* pskkey;
} presharedkey;
struct {
/* Certificate files */
char* filecert;
char* filekey;
char* fileca;
} cert;
};
};
/* */
int capwap_crypt_init();
void capwap_crypt_free();
int capwap_crypt_createcontext(struct capwap_dtls_context* dtlscontext, struct capwap_dtls_param* param);
void capwap_crypt_freecontext(struct capwap_dtls_context* dtlscontext);
void capwap_crypt_setconnection(struct capwap_dtls* dtls, int sock, union sockaddr_capwap* localaddr, union sockaddr_capwap* peeraddr);
int capwap_crypt_createsession(struct capwap_dtls* dtls, struct capwap_dtls_context* dtlscontext);
void capwap_crypt_freesession(struct capwap_dtls* dtls);
int capwap_crypt_open(struct capwap_dtls* dtls);
void capwap_crypt_close(struct capwap_dtls* dtls);
int capwap_crypt_sendto(struct capwap_dtls* dtls, void* buffer, int size);
int capwap_crypt_sendto_fragmentpacket(struct capwap_dtls* dtls, struct capwap_list* fragmentlist);
int capwap_decrypt_packet(struct capwap_dtls* dtls, void* encrybuffer, int size, void* plainbuffer, int maxsize);
int capwap_crypt_has_dtls_clienthello(void* buffer, int buffersize);
#endif /* __CAPWAP_DTLS_HEADER__ */

680
lib/element.c Normal file
View File

@ -0,0 +1,680 @@
#include "capwap.h"
#include "element.h"
#include "protocol.h"
#include "array.h"
/* */
#define element_ops(Id, Ops) [(Id) - CAPWAP_MESSAGE_ELEMENTS_START] = &(Ops)
static const struct capwap_message_elements_ops * capwap_message_elements[] = {
element_ops(CAPWAP_ELEMENT_ACDESCRIPTION_TYPE, capwap_element_acdescriptor_ops),
element_ops(CAPWAP_ELEMENT_ACIPV4LIST_TYPE, capwap_element_acipv4list_ops),
element_ops(CAPWAP_ELEMENT_ACIPV6LIST_TYPE, capwap_element_acipv6list_ops),
element_ops(CAPWAP_ELEMENT_ACNAME_TYPE, capwap_element_acname_ops),
element_ops(CAPWAP_ELEMENT_ACNAMEPRIORITY_TYPE, capwap_element_acnamepriority_ops),
element_ops(CAPWAP_ELEMENT_ACTIMESTAMP_TYPE, capwap_element_actimestamp_ops),
element_ops(CAPWAP_ELEMENT_ADDMACACL_TYPE, capwap_element_addmacacl_ops),
element_ops(CAPWAP_ELEMENT_ADDSTATION_TYPE, capwap_element_addstation_ops),
element_ops(CAPWAP_ELEMENT_CONTROLIPV4_TYPE, capwap_element_controlipv4_ops),
element_ops(CAPWAP_ELEMENT_CONTROLIPV6_TYPE, capwap_element_controlipv6_ops),
element_ops(CAPWAP_ELEMENT_TIMERS_TYPE, capwap_element_timers_ops),
element_ops(CAPWAP_ELEMENT_DATATRANSFERDATA_TYPE, capwap_element_datatransferdata_ops),
element_ops(CAPWAP_ELEMENT_DATATRANSFERMODE_TYPE, capwap_element_datatransfermode_ops),
element_ops(CAPWAP_ELEMENT_DECRYPTERRORREPORT_TYPE, capwap_element_decrypterrorreport_ops),
element_ops(CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD_TYPE, capwap_element_decrypterrorreportperiod_ops),
element_ops(CAPWAP_ELEMENT_DELETEMACACL_TYPE, capwap_element_deletemacacl_ops),
element_ops(CAPWAP_ELEMENT_DELETESTATION_TYPE, capwap_element_deletestation_ops),
element_ops(CAPWAP_ELEMENT_DISCOVERYTYPE_TYPE, capwap_element_discoverytype_ops),
element_ops(CAPWAP_ELEMENT_DUPLICATEIPV4_TYPE, capwap_element_duplicateipv4_ops),
element_ops(CAPWAP_ELEMENT_DUPLICATEIPV6_TYPE, capwap_element_duplicateipv6_ops),
element_ops(CAPWAP_ELEMENT_IDLETIMEOUT_TYPE, capwap_element_idletimeout_ops),
element_ops(CAPWAP_ELEMENT_IMAGEDATA_TYPE, capwap_element_imagedata_ops),
element_ops(CAPWAP_ELEMENT_IMAGEIDENTIFIER_TYPE, capwap_element_imageidentifier_ops),
element_ops(CAPWAP_ELEMENT_IMAGEINFO_TYPE, capwap_element_imageinfo_ops),
element_ops(CAPWAP_ELEMENT_INITIATEDOWNLOAD_TYPE, capwap_element_initdownload_ops),
element_ops(CAPWAP_ELEMENT_LOCATION_TYPE, capwap_element_location_ops),
element_ops(CAPWAP_ELEMENT_MAXIMUMLENGTH_TYPE, capwap_element_maximumlength_ops),
element_ops(CAPWAP_ELEMENT_LOCALIPV4_TYPE, capwap_element_localipv4_ops),
element_ops(CAPWAP_ELEMENT_RADIOADMSTATE_TYPE, capwap_element_radioadmstate_ops),
element_ops(CAPWAP_ELEMENT_RADIOOPRSTATE_TYPE, capwap_element_radiooprstate_ops),
element_ops(CAPWAP_ELEMENT_RESULTCODE_TYPE, capwap_element_resultcode_ops),
element_ops(CAPWAP_ELEMENT_RETURNEDMESSAGE_TYPE, capwap_element_returnedmessage_ops),
element_ops(CAPWAP_ELEMENT_SESSIONID_TYPE, capwap_element_sessionid_ops),
element_ops(CAPWAP_ELEMENT_STATISTICSTIMER_TYPE, capwap_element_statisticstimer_ops),
element_ops(CAPWAP_ELEMENT_VENDORPAYLOAD_TYPE, capwap_element_vendorpayload_ops),
element_ops(CAPWAP_ELEMENT_WTPBOARDDATA_TYPE, capwap_element_wtpboarddata_ops),
element_ops(CAPWAP_ELEMENT_WTPDESCRIPTOR_TYPE, capwap_element_wtpdescriptor_ops),
element_ops(CAPWAP_ELEMENT_WTPFALLBACK_TYPE, capwap_element_wtpfallback_ops),
element_ops(CAPWAP_ELEMENT_WTPFRAMETUNNELMODE_TYPE, capwap_element_wtpframetunnelmode_ops),
element_ops(CAPWAP_ELEMENT_WTPMACTYPE_TYPE, capwap_element_wtpmactype_ops),
element_ops(CAPWAP_ELEMENT_WTPNAME_TYPE, capwap_element_wtpname_ops),
element_ops(CAPWAP_ELEMENT_WTPRADIOSTAT_TYPE, capwap_element_wtpradiostat_ops),
element_ops(CAPWAP_ELEMENT_WTPREBOOTSTAT_TYPE, capwap_element_wtprebootstat_ops),
element_ops(CAPWAP_ELEMENT_WTPSTATICIPADDRESS_TYPE, capwap_element_wtpstaticipaddress_ops),
element_ops(CAPWAP_ELEMENT_LOCALIPV6_TYPE, capwap_element_localipv6_ops),
element_ops(CAPWAP_ELEMENT_TRANSPORT_TYPE, capwap_element_transport_ops),
element_ops(CAPWAP_ELEMENT_MTUDISCOVERY_TYPE, capwap_element_mtudiscovery_ops),
element_ops(CAPWAP_ELEMENT_ECNSUPPORT_TYPE, capwap_element_ecnsupport_ops)
};
#undef element_ops
/* */
#define element_ops(Id, Ops) [(Id) - CAPWAP_80211_MESSAGE_ELEMENTS_START] = &(Ops)
static const struct capwap_message_elements_ops * capwap_80211_message_elements[] = {
element_ops(CAPWAP_ELEMENT_80211_ADD_WLAN_TYPE, capwap_element_80211_addwlan_ops),
element_ops(CAPWAP_ELEMENT_80211_ANTENNA_TYPE, capwap_element_80211_antenna_ops),
element_ops(CAPWAP_ELEMENT_80211_ASSIGN_BSSID_TYPE, capwap_element_80211_assignbssid_ops),
element_ops(CAPWAP_ELEMENT_80211_DELETE_WLAN_TYPE, capwap_element_80211_deletewlan_ops),
element_ops(CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL_TYPE, capwap_element_80211_directsequencecontrol_ops),
element_ops(CAPWAP_ELEMENT_80211_IE_TYPE, capwap_element_80211_ie_ops),
element_ops(CAPWAP_ELEMENT_80211_MAC_PROFILE_TYPE, capwap_element_80211_mac_profile_ops),
element_ops(CAPWAP_ELEMENT_80211_MACOPERATION_TYPE, capwap_element_80211_macoperation_ops),
element_ops(CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES_TYPE, capwap_element_80211_miccountermeasures_ops),
element_ops(CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY_TYPE, capwap_element_80211_multidomaincapability_ops),
element_ops(CAPWAP_ELEMENT_80211_OFDMCONTROL_TYPE, capwap_element_80211_ofdmcontrol_ops),
element_ops(CAPWAP_ELEMENT_80211_RATESET_TYPE, capwap_element_80211_rateset_ops),
element_ops(CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT_TYPE, capwap_element_80211_rsnaerrorreport_ops),
element_ops(CAPWAP_ELEMENT_80211_STATION_TYPE, capwap_element_80211_station_ops),
element_ops(CAPWAP_ELEMENT_80211_STATION_QOS_PROFILE_TYPE, capwap_element_80211_stationqos_ops),
element_ops(CAPWAP_ELEMENT_80211_STATION_SESSION_KEY_PROFILE_TYPE, capwap_element_80211_stationkey_ops),
element_ops(CAPWAP_ELEMENT_80211_STATISTICS_TYPE, capwap_element_80211_statistics_ops),
element_ops(CAPWAP_ELEMENT_80211_SUPPORTED_MAC_PROFILES_TYPE, capwap_element_80211_supported_mac_profiles_ops),
element_ops(CAPWAP_ELEMENT_80211_SUPPORTEDRATES_TYPE, capwap_element_80211_supportedrates_ops),
element_ops(CAPWAP_ELEMENT_80211_TXPOWER_TYPE, capwap_element_80211_txpower_ops),
element_ops(CAPWAP_ELEMENT_80211_TXPOWERLEVEL_TYPE, capwap_element_80211_txpowerlevel_ops),
element_ops(CAPWAP_ELEMENT_80211_UPDATE_STATION_QOS_TYPE, capwap_element_80211_updatestationqos_ops),
element_ops(CAPWAP_ELEMENT_80211_UPDATE_WLAN_TYPE, capwap_element_80211_updatewlan_ops),
element_ops(CAPWAP_ELEMENT_80211_WTP_QOS_TYPE, capwap_element_80211_wtpqos_ops),
element_ops(CAPWAP_ELEMENT_80211_WTP_RADIO_CONF_TYPE, capwap_element_80211_wtpradioconf_ops),
element_ops(CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM_TYPE, capwap_element_80211_wtpradiofailalarm_ops),
element_ops(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_TYPE, capwap_element_80211_wtpradioinformation_ops)
};
#undef element_ops
/* */
#define element_ops(Id, Ops) [(Id) - 1] = &(Ops)
static const struct capwap_message_elements_ops * capwap_vendor_travelping_message_elements[] = {
element_ops(CAPWAP_ELEMENT_VENDOR_TRAVELPING_WTP_TIMESTAMP_TYPE, capwap_element_vendor_travelping_wtp_timestamp_ops),
element_ops(CAPWAP_ELEMENT_80211N_RADIO_CONF_TYPE, capwap_element_80211n_radioconf_ops),
element_ops(CAPWAP_ELEMENT_80211N_STATION_INFO_TYPE, capwap_element_80211n_station_info_ops),
element_ops(CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_ENCRYPTION_CAPABILITY_TYPE, capwap_element_vendor_travelping_80211_encryption_capability_ops),
element_ops(CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_TYPE, capwap_element_vendor_travelping_80211_update_key_ops)
};
#undef element_ops
/* */
const struct capwap_message_elements_ops *
capwap_get_message_element_ops(const struct capwap_message_element_id id)
{
#define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
switch (id.vendor) {
case 0:
if (id.type >= CAPWAP_MESSAGE_ELEMENTS_START &&
id.type - CAPWAP_MESSAGE_ELEMENTS_START < ARRAY_SIZE(capwap_message_elements)) {
return capwap_message_elements[id.type - CAPWAP_MESSAGE_ELEMENTS_START];
}
else if (id.type >= CAPWAP_80211_MESSAGE_ELEMENTS_START &&
id.type - CAPWAP_80211_MESSAGE_ELEMENTS_START < ARRAY_SIZE(capwap_80211_message_elements)) {
return capwap_80211_message_elements[id.type - CAPWAP_80211_MESSAGE_ELEMENTS_START];
}
break;
case CAPWAP_VENDOR_TRAVELPING_ID:
if (id.type >= 1 &&
id.type - 1 < ARRAY_SIZE(capwap_vendor_travelping_message_elements))
return capwap_vendor_travelping_message_elements[id.type - 1];
break;
}
return NULL;
#undef ARRAY_SIZE
}
/* */
struct capwap_list_item* capwap_get_message_element(struct capwap_parsed_packet* packet,
const struct capwap_message_element_id id)
{
struct capwap_list_item* search;
ASSERT(packet != NULL);
ASSERT(packet->messages != NULL);
search = packet->messages->first;
while (search) {
struct capwap_message_element_itemlist* messageelement =
(struct capwap_message_element_itemlist*)search->item;
if (message_element_id_eq(id, messageelement->id))
return search;
/* */
search = search->next;
}
return NULL;
}
/* */
void* capwap_get_message_element_data(struct capwap_parsed_packet* packet,
const struct capwap_message_element_id id)
{
struct capwap_list_item* itemlist;
struct capwap_message_element_itemlist* messageelement;
/* Retrieve item list */
itemlist = capwap_get_message_element(packet, id);
if (!itemlist) {
return NULL;
}
/* Get message element info */
messageelement = (struct capwap_message_element_itemlist*)itemlist->item;
ASSERT(messageelement != NULL);
return messageelement->data;
}
/* */
int capwap_parsing_packet(struct capwap_packet_rxmng* rxmngpacket, struct capwap_parsed_packet* packet) {
unsigned short binding;
unsigned short bodylength;
ASSERT(rxmngpacket != NULL);
ASSERT(packet != NULL);
/* */
memset(packet, 0, sizeof(struct capwap_parsed_packet));
packet->rxmngpacket = rxmngpacket;
packet->messages = capwap_list_create();
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
/* Position reader to capwap body */
memcpy(&rxmngpacket->readpos, &rxmngpacket->readbodypos, sizeof(struct read_block_from_pos));
/* */
bodylength = rxmngpacket->ctrlmsg.length - CAPWAP_CONTROL_MESSAGE_MIN_LENGTH;
while (bodylength > 0) {
struct capwap_message_element_id id = { .vendor = 0 };
uint16_t msglength;
struct capwap_list_item* itemlist;
struct capwap_message_element_itemlist* messageelement;
void *element;
const struct capwap_message_elements_ops* read_ops;
/* Get type and length */
rxmngpacket->readerpacketallowed = sizeof(struct capwap_message_element);
if (rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &id.type) != sizeof(uint16_t) ||
rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &msglength) != sizeof(uint16_t) ||
msglength > bodylength)
return INVALID_MESSAGE_ELEMENT;
/* Allowed to parsing only the size of message element */
rxmngpacket->readerpacketallowed = msglength;
/* Check binding */
if (IS_80211_MESSAGE_ELEMENTS(id) &&
(binding != CAPWAP_WIRELESS_BINDING_IEEE80211))
return UNRECOGNIZED_MESSAGE_ELEMENT;
log_printf(LOG_DEBUG, "MESSAGE ELEMENT: %d", id.type);
if (id.type == CAPWAP_ELEMENT_VENDORPAYLOAD_TYPE) {
struct capwap_message_element_id vendor_id;
if (msglength < 7) {
log_printf(LOG_DEBUG, "Invalid Vendor Specific Payload element: underbuffer");
return INVALID_MESSAGE_ELEMENT;
}
if ((msglength - 6) > CAPWAP_VENDORPAYLOAD_MAXLENGTH) {
log_printf(LOG_DEBUG, "Invalid Vendor Specific Payload element: overbuffer");
return INVALID_MESSAGE_ELEMENT;
}
rxmngpacket->read_ops.read_u32((capwap_message_elements_handle)rxmngpacket, &vendor_id.vendor);
rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &vendor_id.type);
log_printf(LOG_DEBUG, "VENDOR MESSAGE ELEMENT: %06x:%d", vendor_id.vendor, vendor_id.type);
read_ops = capwap_get_message_element_ops(vendor_id);
log_printf(LOG_DEBUG, "vendor read_ops: %p", read_ops);
if (read_ops) {
id = vendor_id;
element = read_ops->parse((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->read_ops);
} else {
read_ops = capwap_get_message_element_ops(id);
element = capwap_unknown_vendorpayload_element_parsing((capwap_message_elements_handle)rxmngpacket,
&rxmngpacket->read_ops, msglength - 6, vendor_id);
}
} else {
/* Reader function */
read_ops = capwap_get_message_element_ops(id);
log_printf(LOG_DEBUG, "read_ops: %p", read_ops);
if (!read_ops)
return UNRECOGNIZED_MESSAGE_ELEMENT;
/* Get message element */
element = read_ops->parse((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->read_ops);
}
if (!element)
return INVALID_MESSAGE_ELEMENT;
/* */
itemlist = capwap_get_message_element(packet, id);
if (read_ops->category == CAPWAP_MESSAGE_ELEMENT_SINGLE) {
/* Check for multiple message element */
if (itemlist) {
return INVALID_MESSAGE_ELEMENT;
}
/* Create new message element */
itemlist = capwap_itemlist_create(sizeof(struct capwap_message_element_itemlist));
messageelement = (struct capwap_message_element_itemlist*)itemlist->item;
messageelement->id = id;
messageelement->category = CAPWAP_MESSAGE_ELEMENT_SINGLE;
messageelement->data = element;
/* */
capwap_itemlist_insert_after(packet->messages, NULL, itemlist);
}
else if (read_ops->category == CAPWAP_MESSAGE_ELEMENT_ARRAY) {
struct capwap_array* arraymessageelement;
if (itemlist) {
messageelement = (struct capwap_message_element_itemlist*)itemlist->item;
arraymessageelement = (struct capwap_array*)messageelement->data;
} else {
arraymessageelement = capwap_array_create(sizeof(void*), 0, 0);
/* */
itemlist = capwap_itemlist_create(sizeof(struct capwap_message_element_itemlist));
messageelement = (struct capwap_message_element_itemlist*)itemlist->item;
messageelement->id = id;
messageelement->category = CAPWAP_MESSAGE_ELEMENT_ARRAY;
messageelement->data = (void*)arraymessageelement;
/* */
capwap_itemlist_insert_after(packet->messages, NULL, itemlist);
}
/* */
*(void **)capwap_array_get_item_pointer(arraymessageelement, arraymessageelement->count) = element;
}
/* Check if read all data of message element */
if (rxmngpacket->readerpacketallowed) {
return INVALID_MESSAGE_ELEMENT;
}
/* */
bodylength -= (msglength + sizeof(struct capwap_message_element));
}
return PARSING_COMPLETE;
}
/* */
int capwap_validate_parsed_packet(struct capwap_parsed_packet* packet, struct capwap_array* returnedmessage) {
unsigned short binding;
struct capwap_resultcode_element* resultcode;
ASSERT(packet != NULL);
ASSERT(packet->rxmngpacket != NULL);
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
switch (packet->rxmngpacket->ctrlmsg.type) {
case CAPWAP_DISCOVERY_REQUEST: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_DISCOVERYTYPE) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPBOARDDATA) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPDESCRIPTOR) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFRAMETUNNELMODE) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPMACTYPE)) {
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION)) {
return 0;
}
} else {
return 0;
}
}
break;
}
case CAPWAP_DISCOVERY_RESPONSE: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ACDESCRIPTION) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAME) &&
(capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV6))) {
return 0;
}
/* Check if packet contains Result Code with Error Message */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
return 0;
}
break;
}
case CAPWAP_JOIN_REQUEST: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCATION) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPBOARDDATA) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPDESCRIPTOR) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPNAME) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_SESSIONID) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFRAMETUNNELMODE) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPMACTYPE) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_ECNSUPPORT) &&
(capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCALIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCALIPV6))) {
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION)) {
return 0;
}
} else {
return 0;
}
}
break;
}
case CAPWAP_JOIN_RESPONSE: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_ACDESCRIPTION) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAME) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_ECNSUPPORT) &&
(capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV6)) &&
(capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCALIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCALIPV6))) {
return 0;
}
/* Check if packet contains Result Code with Error Message */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
return 0;
}
break;
}
case CAPWAP_CONFIGURATION_STATUS_REQUEST: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAME) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_RADIOADMSTATE) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_STATISTICSTIMER) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPREBOOTSTAT)) {
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION)) {
return 0;
}
} else {
return 0;
}
}
break;
}
case CAPWAP_CONFIGURATION_STATUS_RESPONSE: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_TIMERS) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_IDLETIMEOUT) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFALLBACK) &&
(capwap_get_message_element(packet, CAPWAP_ELEMENT_ACIPV4LIST) || capwap_get_message_element(packet, CAPWAP_ELEMENT_ACIPV6LIST))) {
return 0;
}
/* Check if packet contains Result Code with Error Message */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
return 0;
}
break;
}
case CAPWAP_CONFIGURATION_UPDATE_REQUEST: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAMEPRIORITY) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_ACTIMESTAMP) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_ADDMACACL) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_TIMERS) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_DELETEMACACL) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_IDLETIMEOUT) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCATION) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_RADIOADMSTATE) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_STATISTICSTIMER) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFALLBACK) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPNAME) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPSTATICIPADDRESS) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_IMAGEIDENTIFIER) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_VENDORPAYLOAD)) {
return 0;
}
break;
}
case CAPWAP_CONFIGURATION_UPDATE_RESPONSE: {
return 0;
}
case CAPWAP_WTP_EVENT_REQUEST: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_DUPLICATEIPV4) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_DUPLICATEIPV6) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPRADIOSTAT) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPREBOOTSTAT) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_DELETESTATION) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_VENDORPAYLOAD)) {
return 0;
}
break;
}
case CAPWAP_WTP_EVENT_RESPONSE: {
return 0;
}
case CAPWAP_CHANGE_STATE_EVENT_REQUEST: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RADIOOPRSTATE) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) {
return 0;
}
break;
}
case CAPWAP_CHANGE_STATE_EVENT_RESPONSE: {
return 0;
}
case CAPWAP_ECHO_REQUEST: {
return 0;
}
case CAPWAP_ECHO_RESPONSE: {
return 0;
}
case CAPWAP_IMAGE_DATA_REQUEST: {
return 0;
}
case CAPWAP_IMAGE_DATA_RESPONSE: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) {
return 0;
}
break;
}
case CAPWAP_RESET_REQUEST: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_IMAGEIDENTIFIER)) {
return 0;
}
break;
}
case CAPWAP_RESET_RESPONSE: {
return 0;
}
case CAPWAP_PRIMARY_DISCOVERY_REQUEST: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_DISCOVERYTYPE) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPBOARDDATA) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPDESCRIPTOR) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFRAMETUNNELMODE) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPMACTYPE)) {
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION)) {
return 0;
}
} else {
return 0;
}
}
break;
}
case CAPWAP_PRIMARY_DISCOVERY_RESPONSE: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ACDESCRIPTION) &&
capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAME) &&
(capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV6))) {
return 0;
}
/* Check if packet contains Result Code with Error Message */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
return 0;
}
break;
}
case CAPWAP_DATA_TRANSFER_REQUEST: {
/* TODO */
break;
}
case CAPWAP_DATA_TRANSFER_RESPONSE: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) {
return 0;
}
break;
}
case CAPWAP_CLEAR_CONFIGURATION_REQUEST: {
return 0;
}
case CAPWAP_CLEAR_CONFIGURATION_RESPONSE: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) {
return 0;
}
break;
}
case CAPWAP_STATION_CONFIGURATION_REQUEST: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ADDSTATION)) {
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_STATION)) {
return 0;
}
} else {
return 0;
}
} else if (capwap_get_message_element(packet, CAPWAP_ELEMENT_DELETESTATION)) {
return 0;
}
break;
}
case CAPWAP_STATION_CONFIGURATION_RESPONSE: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) {
return 0;
}
break;
}
case CAPWAP_IEEE80211_WLAN_CONFIGURATION_REQUEST: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_ADD_WLAN) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_UPDATE_WLAN) ||
capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_DELETE_WLAN)) {
return 0;
}
break;
}
case CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE: {
if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) {
return 0;
}
break;
}
}
return -1;
}
/* */
void capwap_free_parsed_packet(struct capwap_parsed_packet* packet) {
int i;
struct capwap_list_item* itemlist;
struct capwap_message_element_itemlist* messageelement;
const struct capwap_message_elements_ops* msgops;
ASSERT(packet != NULL);
if (packet->rxmngpacket && packet->messages) {
itemlist = packet->messages->first;
while (itemlist) {
messageelement = (struct capwap_message_element_itemlist*)itemlist->item;
if (messageelement->data) {
msgops = capwap_get_message_element_ops(messageelement->id);
if (messageelement->category == CAPWAP_MESSAGE_ELEMENT_SINGLE) {
msgops->free(messageelement->data);
} else if (messageelement->category == CAPWAP_MESSAGE_ELEMENT_ARRAY) {
struct capwap_array* arraymessageelement = (struct capwap_array*)messageelement->data;
for (i = 0; i < arraymessageelement->count; i++) {
msgops->free(*(void**)capwap_array_get_item_pointer(arraymessageelement, i));
}
/* */
capwap_array_free(arraymessageelement);
}
}
/* */
itemlist = itemlist->next;
}
/* */
packet->rxmngpacket = NULL;
capwap_list_free(packet->messages);
packet->messages = NULL;
}
}

169
lib/element.h Normal file
View File

@ -0,0 +1,169 @@
#ifndef __CAPWAP_ELEMENT_HEADER__
#define __CAPWAP_ELEMENT_HEADER__
#include "array.h"
#include "list.h"
struct capwap_message_element_id
{
uint32_t vendor;
uint16_t type;
};
#define message_element_id_eq(a, b) \
(((a).vendor == (b).vendor) && ((a).type == (b).type))
/* */
typedef void* capwap_message_elements_handle;
struct capwap_write_message_elements_ops {
int (*write_u8)(capwap_message_elements_handle handle, uint8_t data);
int (*write_u16)(capwap_message_elements_handle handle, uint16_t data);
int (*write_u32)(capwap_message_elements_handle handle, uint32_t data);
int (*write_block)(capwap_message_elements_handle handle, const uint8_t* data, unsigned short length);
};
struct capwap_read_message_elements_ops {
unsigned short (*read_ready)(capwap_message_elements_handle handle);
int (*read_u8)(capwap_message_elements_handle handle, uint8_t* data);
int (*read_u16)(capwap_message_elements_handle handle, uint16_t* data);
int (*read_u32)(capwap_message_elements_handle handle, uint32_t* data);
int (*read_block)(capwap_message_elements_handle handle, uint8_t* data, unsigned short length);
};
struct capwap_message_elements_ops
{
int category;
/* Build message element */
void (*create)(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func);
/* Parsing message element */
void* (*parse)(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func);
/* Memory management */
void* (*clone)(void*);
void (*free)(void*);
};
const struct capwap_message_elements_ops *capwap_get_message_element_ops(const struct capwap_message_element_id id);
/*********************************************************************************************************************/
/* Standard message elements */
#include "element_acdescriptor.h" /* 00001 */
#include "element_acipv4list.h" /* 00002 */
#include "element_acipv6list.h" /* 00003 */
#include "element_acname.h" /* 00004 */
#include "element_acnamepriority.h" /* 00005 */
#include "element_actimestamp.h" /* 00006 */
#include "element_addmacacl.h" /* 00007 */
#include "element_addstation.h" /* 00008 */
/* Reserved */ /* 00009 */
#include "element_controlipv4.h" /* 00010 */
#include "element_controlipv6.h" /* 00011 */
#include "element_timers.h" /* 00012 */
#include "element_datatransferdata.h" /* 00013 */
#include "element_datatransfermode.h" /* 00014 */
#include "element_decrypterrorreport.h" /* 00015 */
#include "element_decrypterrorreportperiod.h" /* 00016 */
#include "element_deletemacacl.h" /* 00017 */
#include "element_deletestation.h" /* 00018 */
/* Reserved */ /* 00019 */
#include "element_discoverytype.h" /* 00020 */
#include "element_duplicateipv4.h" /* 00021 */
#include "element_duplicateipv6.h" /* 00022 */
#include "element_idletimeout.h" /* 00023 */
#include "element_imagedata.h" /* 00024 */
#include "element_imageidentifier.h" /* 00025 */
#include "element_imageinfo.h" /* 00026 */
#include "element_initdownload.h" /* 00027 */
#include "element_location.h" /* 00028 */
#include "element_maximumlength.h" /* 00029 */
#include "element_localipv4.h" /* 00030 */
#include "element_radioadmstate.h" /* 00031 */
#include "element_radiooprstate.h" /* 00032 */
#include "element_resultcode.h" /* 00033 */
#include "element_returnedmessage.h" /* 00034 */
#include "element_sessionid.h" /* 00035 */
#include "element_statisticstimer.h" /* 00036 */
#include "element_vendorpayload.h" /* 00037 */
#include "element_wtpboarddata.h" /* 00038 */
#include "element_wtpdescriptor.h" /* 00039 */
#include "element_wtpfallback.h" /* 00040 */
#include "element_wtpframetunnelmode.h" /* 00041 */
/* Reserved */ /* 00042 */
/* Reserved */ /* 00043 */
#include "element_wtpmactype.h" /* 00044 */
#include "element_wtpname.h" /* 00045 */
/* Reserved */ /* 00046 */
#include "element_wtpradiostat.h" /* 00047 */
#include "element_wtprebootstat.h" /* 00048 */
#include "element_wtpstaticipaddress.h" /* 00049 */
#include "element_localipv6.h" /* 00050 */
#include "element_transport.h" /* 00051 */
#include "element_mtudiscovery.h" /* 00052 */
#include "element_ecnsupport.h" /* 00053 */
/* IEEE 802.11 message elements */
#include "element_80211_addwlan.h" /* 01024 */
#include "element_80211_antenna.h" /* 01025 */
#include "element_80211_assignbssid.h" /* 01026 */
#include "element_80211_deletewlan.h" /* 01027 */
#include "element_80211_directsequencecontrol.h" /* 01028 */
#include "element_80211_ie.h" /* 01029 */
#include "element_80211_macoperation.h" /* 01030 */
#include "element_80211_miccountermeasures.h" /* 01031 */
#include "element_80211_multidomaincapability.h" /* 01032 */
#include "element_80211_ofdmcontrol.h" /* 01033 */
#include "element_80211_rateset.h" /* 01034 */
#include "element_80211_rsnaerrorreport.h" /* 01035 */
#include "element_80211_station.h" /* 01036 */
#include "element_80211_stationqos.h" /* 01037 */
#include "element_80211_stationkey.h" /* 01038 */
#include "element_80211_statistics.h" /* 01039 */
#include "element_80211_supportedrates.h" /* 01040 */
#include "element_80211_txpower.h" /* 01041 */
#include "element_80211_txpowerlevel.h" /* 01042 */
#include "element_80211_updatestationqos.h" /* 01043 */
#include "element_80211_updatewlan.h" /* 01044 */
#include "element_80211_wtpqos.h" /* 01045 */
#include "element_80211_wtpradioconf.h" /* 01046 */
#include "element_80211_wtpradiofailalarm.h" /* 01047 */
#include "element_80211_wtpradioinformation.h" /* 01048 */
#include "element_80211_supported_mac_profiles.h" /* 01060 */
#include "element_80211_mac_profile.h" /* 01061 */
#include "vendor_travelping.h"
/*********************************************************************************************************************/
#define CAPWAP_MESSAGE_ELEMENT_SINGLE 0
#define CAPWAP_MESSAGE_ELEMENT_ARRAY 1
int capwap_get_message_element_category(uint16_t type);
struct capwap_message_element_itemlist
{
struct capwap_message_element_id id;
int category;
void* data;
};
struct capwap_parsed_packet {
struct capwap_packet_rxmng* rxmngpacket;
struct capwap_list* messages;
};
/* */
#define PARSING_COMPLETE 0
#define UNRECOGNIZED_MESSAGE_ELEMENT 1
#define INVALID_MESSAGE_ELEMENT 2
int capwap_parsing_packet(struct capwap_packet_rxmng* rxmngpacket, struct capwap_parsed_packet* packet);
int capwap_validate_parsed_packet(struct capwap_parsed_packet* packet, struct capwap_array* returnedmessage);
void capwap_free_parsed_packet(struct capwap_parsed_packet* packet);
struct capwap_list_item *capwap_get_message_element(struct capwap_parsed_packet *packet,
const struct capwap_message_element_id id);
void *capwap_get_message_element_data(struct capwap_parsed_packet *packet,
const struct capwap_message_element_id id);
#endif /* __CAPWAP_ELEMENT_HEADER__ */

162
lib/element_80211_addwlan.c Normal file
View File

@ -0,0 +1,162 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | WLAN ID | Capability |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Key Index | Key Status | Key Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Key... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Group TSC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Group TSC | QoS | Auth Type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| MAC Mode | Tunnel Mode | Suppress SSID | SSID ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1024 for IEEE 802.11 Add WLAN
Length: >= 20
********************************************************************/
/* */
static void capwap_80211_addwlan_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
int length;
struct capwap_80211_addwlan_element* element = (struct capwap_80211_addwlan_element*)data;
ASSERT(data != NULL);
ASSERT(IS_VALID_RADIOID(element->radioid));
ASSERT(IS_VALID_WLANID(element->wlanid));
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->wlanid);
func->write_u16(handle, element->capability);
func->write_u8(handle, element->keyindex);
func->write_u8(handle, element->keystatus);
func->write_u16(handle, element->keylength);
if ((element->keylength > 0) && element->key) {
func->write_block(handle, element->key, element->keylength);
}
func->write_block(handle, element->grouptsc, CAPWAP_ADD_WLAN_GROUPTSC_LENGTH);
func->write_u8(handle, element->qos);
func->write_u8(handle, element->authmode);
func->write_u8(handle, element->macmode);
func->write_u8(handle, element->tunnelmode);
func->write_u8(handle, element->suppressssid);
length = strlen((char*)element->ssid);
ASSERT((length > 0) && (length <= CAPWAP_ADD_WLAN_SSID_LENGTH));
func->write_block(handle, element->ssid, length);
}
/* */
static void* capwap_80211_addwlan_element_clone(void* data) {
struct capwap_80211_addwlan_element* cloneelement;
struct capwap_80211_addwlan_element* element = (struct capwap_80211_addwlan_element*)data;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_80211_addwlan_element));
if (cloneelement->keylength > 0) {
cloneelement->key = capwap_clone(element->key, cloneelement->keylength);
}
cloneelement->ssid = (uint8_t*)capwap_duplicate_string((char*)element->ssid);
return cloneelement;
}
/* */
static void capwap_80211_addwlan_element_free(void* data) {
struct capwap_80211_addwlan_element* element = (struct capwap_80211_addwlan_element*)data;
ASSERT(data != NULL);
if (element->ssid) {
capwap_free(element->ssid);
}
if (element->key) {
capwap_free(element->key);
}
capwap_free(data);
}
/* */
static void* capwap_80211_addwlan_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
unsigned short length;
struct capwap_80211_addwlan_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 20) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Add WLAN element: underbuffer");
return NULL;
}
/* */
data = (struct capwap_80211_addwlan_element*)capwap_alloc(sizeof(struct capwap_80211_addwlan_element));
memset(data, 0, sizeof(struct capwap_80211_addwlan_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->wlanid);
if (!IS_VALID_RADIOID(data->radioid)) {
capwap_80211_addwlan_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Add WLAN element: invalid radioid");
return NULL;
} else if (!IS_VALID_WLANID(data->wlanid)) {
capwap_80211_addwlan_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Add WLAN element: invalid wlanid");
return NULL;
}
func->read_u16(handle, &data->capability);
func->read_u8(handle, &data->keyindex);
func->read_u8(handle, &data->keystatus);
func->read_u16(handle, &data->keylength);
if (data->keylength > 0) {
data->key = (uint8_t*)capwap_alloc(data->keylength);
func->read_block(handle, data->key, data->keylength);
}
func->read_block(handle, data->grouptsc, CAPWAP_ADD_WLAN_GROUPTSC_LENGTH);
func->read_u8(handle, &data->qos);
func->read_u8(handle, &data->authmode);
func->read_u8(handle, &data->macmode);
func->read_u8(handle, &data->tunnelmode);
func->read_u8(handle, &data->suppressssid);
length = func->read_ready(handle);
if (!length || (length > CAPWAP_ADD_WLAN_SSID_LENGTH)) {
capwap_80211_addwlan_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Add WLAN element: invalid ssid");
return NULL;
}
data->ssid = (uint8_t*)capwap_alloc(length + 1);
func->read_block(handle, data->ssid, length);
data->ssid[length] = 0;
return data;
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_addwlan_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_80211_addwlan_element_create,
.parse = capwap_80211_addwlan_element_parsing,
.clone = capwap_80211_addwlan_element_clone,
.free = capwap_80211_addwlan_element_free
};

View File

@ -0,0 +1,67 @@
#ifndef __CAPWAP_ELEMENT_80211_ADD_WLAN_HEADER__
#define __CAPWAP_ELEMENT_80211_ADD_WLAN_HEADER__
#define CAPWAP_ELEMENT_80211_ADD_WLAN_VENDOR 0
#define CAPWAP_ELEMENT_80211_ADD_WLAN_TYPE 1024
#define CAPWAP_ELEMENT_80211_ADD_WLAN (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_ADD_WLAN_VENDOR, .type = CAPWAP_ELEMENT_80211_ADD_WLAN_TYPE }
#define CAPWAP_ADD_WLAN_GROUPTSC_LENGTH 6
#define CAPWAP_ADD_WLAN_SSID_LENGTH 32
#define CAPWAP_ADD_WLAN_CAPABILITY_ESS 0x0001
#define CAPWAP_ADD_WLAN_CAPABILITY_IBSS 0x0002
#define CAPWAP_ADD_WLAN_CAPABILITY_CFPOLLABLE 0x0004
#define CAPWAP_ADD_WLAN_CAPABILITY_CFPOLLREQUEST 0x0008
#define CAPWAP_ADD_WLAN_CAPABILITY_PRIVACY 0x0010
#define CAPWAP_ADD_WLAN_CAPABILITY_SHORTPREAMBLE 0x0020
#define CAPWAP_ADD_WLAN_CAPABILITY_PBCC 0x0040
#define CAPWAP_ADD_WLAN_CAPABILITY_CHANNELAGILITY 0x0080
#define CAPWAP_ADD_WLAN_CAPABILITY_SPECTRUMMAN 0x0100
#define CAPWAP_ADD_WLAN_CAPABILITY_QOS 0x0200
#define CAPWAP_ADD_WLAN_CAPABILITY_SHORTSLOTTIME 0x0400
#define CAPWAP_ADD_WLAN_CAPABILITY_APSD 0x0800
#define CAPWAP_ADD_WLAN_CAPABILITY_DSSS_OFDM 0x2000
#define CAPWAP_ADD_WLAN_CAPABILITY_DELAYEDACK 0x4000
#define CAPWAP_ADD_WLAN_CAPABILITY_IMMEDIATEACK 0x8000
#define CAPWAP_ADD_WLAN_KEY_STATUS_MULTICASTKEY 0
#define CAPWAP_ADD_WLAN_KEY_STATUS_WEP 1
#define CAPWAP_ADD_WLAN_KEY_STATUS_REKEYINGGTK 2
#define CAPWAP_ADD_WLAN_KEY_STATUS_COMPLETEGTK 3
#define CAPWAP_ADD_WLAN_QOS_BESTEFFORT 0
#define CAPWAP_ADD_WLAN_QOS_VIDEO 1
#define CAPWAP_ADD_WLAN_QOS_VOICE 2
#define CAPWAP_ADD_WLAN_QOS_BACKGROUND 3
#define CAPWAP_ADD_WLAN_AUTHTYPE_OPEN 0
#define CAPWAP_ADD_WLAN_AUTHTYPE_WEP 1
#define CAPWAP_ADD_WLAN_MACMODE_LOCAL 0
#define CAPWAP_ADD_WLAN_MACMODE_SPLIT 1
#define CAPWAP_ADD_WLAN_TUNNELMODE_LOCAL 0
#define CAPWAP_ADD_WLAN_TUNNELMODE_8023 1
#define CAPWAP_ADD_WLAN_TUNNELMODE_80211 2
struct capwap_80211_addwlan_element {
uint8_t radioid;
uint8_t wlanid;
uint16_t capability;
uint8_t keyindex;
uint8_t keystatus;
uint16_t keylength;
uint8_t* key;
uint8_t grouptsc[CAPWAP_ADD_WLAN_GROUPTSC_LENGTH];
uint8_t qos;
uint8_t authmode;
uint8_t macmode;
uint8_t tunnelmode;
uint8_t suppressssid;
uint8_t* ssid;
};
extern const struct capwap_message_elements_ops capwap_element_80211_addwlan_ops;
#endif /* __CAPWAP_ELEMENT_80211_ADD_WLAN_HEADER__ */

151
lib/element_80211_antenna.c Normal file
View File

@ -0,0 +1,151 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Diversity | Combiner | Antenna Cnt |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Antenna Selection...
+-+-+-+-+-+-+-+-+
Type: 1025 for IEEE 802.11 Antenna
Length: >= 5
********************************************************************/
/* */
static void capwap_80211_antenna_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
int i;
struct capwap_80211_antenna_element* element = (struct capwap_80211_antenna_element*)data;
ASSERT(data != NULL);
ASSERT(IS_VALID_RADIOID(element->radioid));
ASSERT(element->selections != NULL);
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->diversity);
func->write_u8(handle, element->combiner);
func->write_u8(handle, element->selections->count);
for (i = 0; i < element->selections->count; i++) {
func->write_u8(handle, *(uint8_t*)capwap_array_get_item_pointer(element->selections, i));
}
}
/* */
static void* capwap_80211_antenna_element_clone(void* data) {
int i;
struct capwap_80211_antenna_element* cloneelement;
struct capwap_80211_antenna_element* element = (struct capwap_80211_antenna_element*)data;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_80211_antenna_element));
cloneelement->selections = capwap_array_create(sizeof(uint8_t), 0, 1);
for (i = 0; i < element->selections->count; i++) {
memcpy(capwap_array_get_item_pointer(cloneelement->selections, i), capwap_array_get_item_pointer(element->selections, i), sizeof(uint8_t));
}
return cloneelement;
}
/* */
static void capwap_80211_antenna_element_free(void* data) {
struct capwap_80211_antenna_element* element = (struct capwap_80211_antenna_element*)data;
ASSERT(data != NULL);
ASSERT(element->selections != NULL);
capwap_array_free(element->selections);
capwap_free(data);
}
/* */
static void* capwap_80211_antenna_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
int i;
uint8_t count;
unsigned short length;
struct capwap_80211_antenna_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 5) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Antenna element");
return NULL;
}
length -= 4;
if (length > CAPWAP_ANTENNASELECTIONS_MAXLENGTH) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Antenna element");
return NULL;
}
/* */
data = (struct capwap_80211_antenna_element*)capwap_alloc(sizeof(struct capwap_80211_antenna_element));
memset(data, 0, sizeof(struct capwap_80211_antenna_element));
data->selections = capwap_array_create(sizeof(uint8_t), 0, 1);
/* Retrieve data */
func->read_u8(handle, &data->radioid);
if (!IS_VALID_RADIOID(data->radioid)) {
capwap_80211_antenna_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Antenna element element: invalid radio");
return NULL;
}
func->read_u8(handle, &data->diversity);
func->read_u8(handle, &data->combiner);
func->read_u8(handle, &count);
/* Check */
if (count != length) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Antenna element");
capwap_free(data);
return NULL;
}
for (i = 0; i < count; i++) {
func->read_u8(handle, (uint8_t*)capwap_array_get_item_pointer(data->selections, i));
}
return data;
}
/* */
void capwap_element_80211_antenna_copy(struct capwap_80211_antenna_element* dst, struct capwap_80211_antenna_element* src) {
int i;
ASSERT(dst != NULL);
ASSERT(src != NULL);
if (dst->selections) {
capwap_array_resize(dst->selections, 0);
} else {
dst->selections = capwap_array_create(sizeof(uint8_t), 0, 1);
}
dst->radioid = src->radioid;
dst->diversity = src->diversity;
dst->combiner = src->combiner;
if (src->selections) {
for (i = 0; i < src->selections->count; i++) {
uint8_t* value = (uint8_t*)capwap_array_get_item_pointer(dst->selections, i);
*value = *(uint8_t*)capwap_array_get_item_pointer(src->selections, i);
}
}
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_antenna_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211_antenna_element_create,
.parse = capwap_80211_antenna_element_parsing,
.clone = capwap_80211_antenna_element_clone,
.free = capwap_80211_antenna_element_free
};

View File

@ -0,0 +1,32 @@
#ifndef __CAPWAP_ELEMENT_80211_ANTENNA_HEADER__
#define __CAPWAP_ELEMENT_80211_ANTENNA_HEADER__
#define CAPWAP_ELEMENT_80211_ANTENNA_VENDOR 0
#define CAPWAP_ELEMENT_80211_ANTENNA_TYPE 1025
#define CAPWAP_ELEMENT_80211_ANTENNA (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_ANTENNA_VENDOR, .type = CAPWAP_ELEMENT_80211_ANTENNA_TYPE }
#define CAPWAP_ANTENNA_DIVERSITY_DISABLE 0
#define CAPWAP_ANTENNA_DIVERSITY_ENABLE 1
#define CAPWAP_ANTENNA_COMBINER_SECT_LEFT 1
#define CAPWAP_ANTENNA_COMBINER_SECT_RIGHT 2
#define CAPWAP_ANTENNA_COMBINER_SECT_OMNI 3
#define CAPWAP_ANTENNA_COMBINER_SECT_MIMO 4
#define CAPWAP_ANTENNA_INTERNAL 1
#define CAPWAP_ANTENNA_EXTERNAL 2
#define CAPWAP_ANTENNASELECTIONS_MAXLENGTH 255
struct capwap_80211_antenna_element {
uint8_t radioid;
uint8_t diversity;
uint8_t combiner;
struct capwap_array* selections;
};
extern const struct capwap_message_elements_ops capwap_element_80211_antenna_ops;
void capwap_element_80211_antenna_copy(struct capwap_80211_antenna_element* dst, struct capwap_80211_antenna_element* src);
#endif /* __CAPWAP_ELEMENT_80211_ANTENNA_HEADER__ */

View File

@ -0,0 +1,76 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | WLAN ID | BSSID
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BSSID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1026 for IEEE 802.11 Assigned WTP BSSID
Length: 8
********************************************************************/
/* */
static void capwap_80211_assignbssid_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_assignbssid_element* element = (struct capwap_80211_assignbssid_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->wlanid);
func->write_block(handle, element->bssid, MACADDRESS_EUI48_LENGTH);
}
/* */
static void* capwap_80211_assignbssid_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_80211_assignbssid_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 8) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Assigned WTP BSSID element");
return NULL;
}
/* */
data = (struct capwap_80211_assignbssid_element*)capwap_alloc(sizeof(struct capwap_80211_assignbssid_element));
memset(data, 0, sizeof(struct capwap_80211_assignbssid_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->wlanid);
func->read_block(handle, data->bssid, MACADDRESS_EUI48_LENGTH);
return data;
}
/* */
static void* capwap_80211_assignbssid_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_assignbssid_element));
}
/* */
static void capwap_80211_assignbssid_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_assignbssid_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_80211_assignbssid_element_create,
.parse = capwap_80211_assignbssid_element_parsing,
.clone = capwap_80211_assignbssid_element_clone,
.free = capwap_80211_assignbssid_element_free
};

View File

@ -0,0 +1,17 @@
#ifndef __CAPWAP_ELEMENT_80211_ASSIGN_BSSID_HEADER__
#define __CAPWAP_ELEMENT_80211_ASSIGN_BSSID_HEADER__
#define CAPWAP_ELEMENT_80211_ASSIGN_BSSID_VENDOR 0
#define CAPWAP_ELEMENT_80211_ASSIGN_BSSID_TYPE 1026
#define CAPWAP_ELEMENT_80211_ASSIGN_BSSID (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_ASSIGN_BSSID_VENDOR, .type = CAPWAP_ELEMENT_80211_ASSIGN_BSSID_TYPE }
struct capwap_80211_assignbssid_element {
uint8_t radioid;
uint8_t wlanid;
uint8_t bssid[MACADDRESS_EUI48_LENGTH];
};
extern const struct capwap_message_elements_ops capwap_element_80211_assignbssid_ops;
#endif /* __CAPWAP_ELEMENT_80211_ASSIGN_BSSID_HEADER__ */

View File

@ -0,0 +1,72 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | WLAN ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1027 for IEEE 802.11 Delete WLAN
Length: 2
********************************************************************/
/* */
static void capwap_80211_deletewlan_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_deletewlan_element* element = (struct capwap_80211_deletewlan_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->wlanid);
}
/* */
static void* capwap_80211_deletewlan_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_80211_deletewlan_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 2) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Delete WLAN element");
return NULL;
}
/* */
data = (struct capwap_80211_deletewlan_element*)capwap_alloc(sizeof(struct capwap_80211_deletewlan_element));
memset(data, 0, sizeof(struct capwap_80211_deletewlan_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->wlanid);
return data;
}
/* */
static void* capwap_80211_deletewlan_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_deletewlan_element));
}
/* */
static void capwap_80211_deletewlan_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_deletewlan_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_80211_deletewlan_element_create,
.parse = capwap_80211_deletewlan_element_parsing,
.clone = capwap_80211_deletewlan_element_clone,
.free = capwap_80211_deletewlan_element_free
};

View File

@ -0,0 +1,16 @@
#ifndef __CAPWAP_ELEMENT_80211_DELETE_WLAN_HEADER__
#define __CAPWAP_ELEMENT_80211_DELETE_WLAN_HEADER__
#define CAPWAP_ELEMENT_80211_DELETE_WLAN_VENDOR 0
#define CAPWAP_ELEMENT_80211_DELETE_WLAN_TYPE 1027
#define CAPWAP_ELEMENT_80211_DELETE_WLAN (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_DELETE_WLAN_VENDOR, .type = CAPWAP_ELEMENT_80211_DELETE_WLAN_TYPE }
struct capwap_80211_deletewlan_element {
uint8_t radioid;
uint8_t wlanid;
};
extern const struct capwap_message_elements_ops capwap_element_80211_deletewlan_ops;
#endif /* __CAPWAP_ELEMENT_80211_DELETE_WLAN_HEADER__ */

View File

@ -0,0 +1,88 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Reserved | Current Chan | Current CCA |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Energy Detect Threshold |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1028 for IEEE 802.11 Direct Sequence Control
Length: 8
********************************************************************/
/* */
static void capwap_80211_directsequencecontrol_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_directsequencecontrol_element* element = (struct capwap_80211_directsequencecontrol_element*)data;
ASSERT(data != NULL);
ASSERT(IS_VALID_RADIOID(element->radioid));
/* */
func->write_u8(handle, element->radioid);
func->write_u8(handle, 0);
func->write_u8(handle, element->currentchannel);
func->write_u8(handle, element->currentcca);
func->write_u32(handle, element->enerydetectthreshold);
}
/* */
static void* capwap_80211_directsequencecontrol_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_directsequencecontrol_element));
}
/* */
static void capwap_80211_directsequencecontrol_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
static void* capwap_80211_directsequencecontrol_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_80211_directsequencecontrol_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 8) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Direct Sequence Control element");
return NULL;
}
/* */
data = (struct capwap_80211_directsequencecontrol_element*)capwap_alloc(sizeof(struct capwap_80211_directsequencecontrol_element));
memset(data, 0, sizeof(struct capwap_80211_directsequencecontrol_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
if (!IS_VALID_RADIOID(data->radioid)) {
capwap_80211_directsequencecontrol_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Direct Sequence Control element: invalid radio");
return NULL;
}
func->read_u8(handle, NULL);
func->read_u8(handle, &data->currentchannel);
func->read_u8(handle, &data->currentcca);
func->read_u32(handle, &data->enerydetectthreshold);
return data;
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_directsequencecontrol_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211_directsequencecontrol_element_create,
.parse = capwap_80211_directsequencecontrol_element_parsing,
.clone = capwap_80211_directsequencecontrol_element_clone,
.free = capwap_80211_directsequencecontrol_element_free
};

View File

@ -0,0 +1,25 @@
#ifndef __CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL_HEADER__
#define __CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL_HEADER__
#define CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL_VENDOR 0
#define CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL_TYPE 1028
#define CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL_VENDOR, .type = CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL_TYPE }
#define CAPWAP_DSCONTROL_CCA_EDONLY 1
#define CAPWAP_DSCONTROL_CCA_CSONLY 2
#define CAPWAP_DSCONTROL_CCA_EDANDCS 4
#define CAPWAP_DSCONTROL_CCA_CSWITHTIME 8
#define CAPWAP_DSCONTROL_CCA_HRCSANDED 16
#define CAPWAP_DSCONTROL_CCA_MASK 0x1f
struct capwap_80211_directsequencecontrol_element {
uint8_t radioid;
uint8_t currentchannel;
uint8_t currentcca;
uint32_t enerydetectthreshold;
};
extern const struct capwap_message_elements_ops capwap_element_80211_directsequencecontrol_ops;
#endif /* __CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL_HEADER__ */

92
lib/element_80211_ie.c Normal file
View File

@ -0,0 +1,92 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | WLAN ID |B|P| Reserved |Info Element...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1029 for IEEE 802.11 Information Element
Length: >= 4
********************************************************************/
/* */
static void capwap_80211_ie_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_ie_element* element = (struct capwap_80211_ie_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->wlanid);
func->write_u8(handle, element->flags);
func->write_block(handle, element->ie, element->ielength);
}
/* */
static void* capwap_80211_ie_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
unsigned short length;
struct capwap_80211_ie_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 4) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Information Element element");
return NULL;
}
/* */
length -= 3;
/* */
data = (struct capwap_80211_ie_element*)capwap_alloc(sizeof(struct capwap_80211_ie_element));
memset(data, 0, sizeof(struct capwap_80211_ie_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->wlanid);
func->read_u8(handle, &data->flags);
data->ielength = length;
data->ie = (uint8_t*)capwap_alloc(data->ielength);
func->read_block(handle, data->ie, data->ielength);
log_printf(LOG_DEBUG, "802.11 IE flags: %02x (%p)", data->flags, &data->flags);
return data;
}
/* */
static void* capwap_80211_ie_element_clone(void* data) {
struct capwap_80211_ie_element* cloneelement;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_80211_ie_element));
cloneelement->ie = capwap_clone(((struct capwap_80211_ie_element*)data)->ie, cloneelement->ielength);
return cloneelement;
}
/* */
static void capwap_80211_ie_element_free(void* data) {
struct capwap_80211_ie_element* element = (struct capwap_80211_ie_element*)data;
ASSERT(data != NULL);
capwap_free(element->ie);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_ie_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211_ie_element_create,
.parse = capwap_80211_ie_element_parsing,
.clone = capwap_80211_ie_element_clone,
.free = capwap_80211_ie_element_free
};

22
lib/element_80211_ie.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef __CAPWAP_ELEMENT_80211_IE_HEADER__
#define __CAPWAP_ELEMENT_80211_IE_HEADER__
#define CAPWAP_ELEMENT_80211_IE_VENDOR 0
#define CAPWAP_ELEMENT_80211_IE_TYPE 1029
#define CAPWAP_ELEMENT_80211_IE (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_IE_VENDOR, .type = CAPWAP_ELEMENT_80211_IE_TYPE }
#define CAPWAP_IE_BEACONS_ASSOCIATED 0x80
#define CAPWAP_IE_PROBE_RESPONSE_ASSOCIATED 0x40
struct capwap_80211_ie_element {
uint8_t radioid;
uint8_t wlanid;
uint8_t flags;
uint16_t ielength;
uint8_t* ie;
};
extern const struct capwap_message_elements_ops capwap_element_80211_ie_ops;
#endif /* __CAPWAP_ELEMENT_80211_IE_HEADER__ */

View File

@ -0,0 +1,89 @@
#include "capwap.h"
#include "element.h"
/*
* The IEEE 802.11 MAC Profile message element allows the AC to select a
* profile. This message element may be provided along with the IEEE
* 802.11 ADD WLAN message element while configuring a WLAN on the WTP.
*
* 0 1 2 3 4 5 6 7
* +=+-+-+-+-+-+-+-+
* | Profile |
* +-+-+-+-+-+-+-+-+
*
* o Type: 1061 for IEEE 802.11 MAC Profile
*
* o Profile: The profile is identified by a value as given below
*
* * 0: This refers to the IEEE 802.11 Split MAC Profile with WTP
* encryption
*
* * 1: This refers to the IEEE 802.11 Split MAC Profile with AC
* encryption
*/
/* */
static void
capwap_80211_mac_profile_element_create(void *data, capwap_message_elements_handle handle,
struct capwap_write_message_elements_ops *func)
{
struct capwap_80211_mac_profile_element *element =
(struct capwap_80211_mac_profile_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->mac_profile);
}
/* */
static void *
capwap_80211_mac_profile_element_parsing(capwap_message_elements_handle handle,
struct capwap_read_message_elements_ops *func)
{
unsigned short length;
struct capwap_80211_mac_profile_element *data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length != 1) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Supported MAC Profiles element");
return NULL;
}
/* */
data = (struct capwap_80211_mac_profile_element *)
capwap_alloc(sizeof(struct capwap_80211_mac_profile_element));
memset(data, 0, sizeof(struct capwap_80211_mac_profile_element));
/* Retrieve data */
func->read_u8(handle, &data->mac_profile);
return data;
}
/* */
static void *capwap_80211_mac_profile_element_clone(void *data)
{
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_mac_profile_element));
}
/* */
static void capwap_80211_mac_profile_element_free(void *data)
{
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_mac_profile_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_80211_mac_profile_element_create,
.parse = capwap_80211_mac_profile_element_parsing,
.clone = capwap_80211_mac_profile_element_clone,
.free = capwap_80211_mac_profile_element_free
};

View File

@ -0,0 +1,18 @@
#ifndef __CAPWAP_ELEMENT_80211_MAC_PROFILE_HEADER__
#define __CAPWAP_ELEMENT_80211_MAC_PROFILE_HEADER__
#define CAPWAP_ELEMENT_80211_MAC_PROFILE_VENDOR 0
#define CAPWAP_ELEMENT_80211_MAC_PROFILE_TYPE 1061
#define CAPWAP_ELEMENT_80211_MAC_PROFILE \
(struct capwap_message_element_id) { \
.vendor = CAPWAP_ELEMENT_80211_MAC_PROFILE_VENDOR, \
.type = CAPWAP_ELEMENT_80211_MAC_PROFILE_TYPE \
}
struct capwap_80211_mac_profile_element {
uint8_t mac_profile;
};
extern const struct capwap_message_elements_ops capwap_element_80211_mac_profile_ops;
#endif /* __CAPWAP_ELEMENT_80211_MAC_PROFILE_HEADER__ */

View File

@ -0,0 +1,91 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Reserved | RTS Threshold |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Short Retry | Long Retry | Fragmentation Threshold |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Tx MSDU Lifetime |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Rx MSDU Lifetime |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1030 for IEEE 802.11 MAC Operation
Length: 16
********************************************************************/
/* */
static void capwap_80211_macoperation_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_macoperation_element* element = (struct capwap_80211_macoperation_element*)data;
ASSERT(data != NULL);
/* */
func->write_u8(handle, element->radioid);
func->write_u8(handle, 0);
func->write_u16(handle, element->rtsthreshold);
func->write_u8(handle, element->shortretry);
func->write_u8(handle, element->longretry);
func->write_u16(handle, element->fragthreshold);
func->write_u32(handle, element->txmsdulifetime);
func->write_u32(handle, element->rxmsdulifetime);
}
/* */
static void* capwap_80211_macoperation_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_80211_macoperation_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 16) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 MAC Operation element");
return NULL;
}
/* */
data = (struct capwap_80211_macoperation_element*)capwap_alloc(sizeof(struct capwap_80211_macoperation_element));
memset(data, 0, sizeof(struct capwap_80211_macoperation_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, NULL);
func->read_u16(handle, &data->rtsthreshold);
func->read_u8(handle, &data->shortretry);
func->read_u8(handle, &data->longretry);
func->read_u16(handle, &data->fragthreshold);
func->read_u32(handle, &data->txmsdulifetime);
func->read_u32(handle, &data->rxmsdulifetime);
return data;
}
/* */
static void* capwap_80211_macoperation_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_macoperation_element));
}
/* */
static void capwap_80211_macoperation_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_macoperation_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211_macoperation_element_create,
.parse = capwap_80211_macoperation_element_parsing,
.clone = capwap_80211_macoperation_element_clone,
.free = capwap_80211_macoperation_element_free
};

View File

@ -0,0 +1,21 @@
#ifndef __CAPWAP_ELEMENT_80211_MACOPERATION_HEADER__
#define __CAPWAP_ELEMENT_80211_MACOPERATION_HEADER__
#define CAPWAP_ELEMENT_80211_MACOPERATION_VENDOR 0
#define CAPWAP_ELEMENT_80211_MACOPERATION_TYPE 1030
#define CAPWAP_ELEMENT_80211_MACOPERATION (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_MACOPERATION_VENDOR, .type = CAPWAP_ELEMENT_80211_MACOPERATION_TYPE }
struct capwap_80211_macoperation_element {
uint8_t radioid;
uint16_t rtsthreshold;
uint8_t shortretry;
uint8_t longretry;
uint16_t fragthreshold;
uint32_t txmsdulifetime;
uint32_t rxmsdulifetime;
};
extern const struct capwap_message_elements_ops capwap_element_80211_macoperation_ops;
#endif /* __CAPWAP_ELEMENT_80211_MACOPERATION_HEADER__ */

View File

@ -0,0 +1,76 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | WLAN ID | BSSID
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BSSID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1031 for IEEE 802.11 MIC Countermeasures
Length: 8
********************************************************************/
/* */
static void capwap_80211_miccountermeasures_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_miccountermeasures_element* element = (struct capwap_80211_miccountermeasures_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->wlanid);
func->write_block(handle, element->address, MACADDRESS_EUI48_LENGTH);
}
/* */
static void* capwap_80211_miccountermeasures_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_80211_miccountermeasures_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 8) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 MIC Countermeasures element");
return NULL;
}
/* */
data = (struct capwap_80211_miccountermeasures_element*)capwap_alloc(sizeof(struct capwap_80211_miccountermeasures_element));
memset(data, 0, sizeof(struct capwap_80211_miccountermeasures_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->wlanid);
func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH);
return data;
}
/* */
static void* capwap_80211_miccountermeasures_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_miccountermeasures_element));
}
/* */
static void capwap_80211_miccountermeasures_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_miccountermeasures_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_80211_miccountermeasures_element_create,
.parse = capwap_80211_miccountermeasures_element_parsing,
.clone = capwap_80211_miccountermeasures_element_clone,
.free = capwap_80211_miccountermeasures_element_free
};

View File

@ -0,0 +1,17 @@
#ifndef __CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES_HEADER__
#define __CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES_HEADER__
#define CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES_VENDOR 0
#define CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES_TYPE 1031
#define CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES_VENDOR, .type = CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES_TYPE }
struct capwap_80211_miccountermeasures_element {
uint8_t radioid;
uint8_t wlanid;
uint8_t address[MACADDRESS_EUI48_LENGTH];
};
extern const struct capwap_message_elements_ops capwap_element_80211_miccountermeasures_ops;
#endif /* __CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES_HEADER__ */

View File

@ -0,0 +1,81 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Reserved | First Channel # |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Number of Channels | Max Tx Power Level |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1032 for IEEE 802.11 Multi-Domain Capability
Length: 8
********************************************************************/
/* */
static void capwap_80211_multidomaincapability_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_multidomaincapability_element* element = (struct capwap_80211_multidomaincapability_element*)data;
ASSERT(data != NULL);
/* */
func->write_u8(handle, element->radioid);
func->write_u8(handle, 0);
func->write_u16(handle, element->firstchannel);
func->write_u16(handle, element->numberchannels);
func->write_u16(handle, element->maxtxpowerlevel);
}
/* */
static void* capwap_80211_multidomaincapability_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_80211_multidomaincapability_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 8) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Multi-Domain Capability element");
return NULL;
}
/* */
data = (struct capwap_80211_multidomaincapability_element*)capwap_alloc(sizeof(struct capwap_80211_multidomaincapability_element));
memset(data, 0, sizeof(struct capwap_80211_multidomaincapability_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, NULL);
func->read_u16(handle, &data->firstchannel);
func->read_u16(handle, &data->numberchannels);
func->read_u16(handle, &data->maxtxpowerlevel);
return data;
}
/* */
static void* capwap_80211_multidomaincapability_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_multidomaincapability_element));
}
/* */
static void capwap_80211_multidomaincapability_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_multidomaincapability_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211_multidomaincapability_element_create,
.parse = capwap_80211_multidomaincapability_element_parsing,
.clone = capwap_80211_multidomaincapability_element_clone,
.free = capwap_80211_multidomaincapability_element_free
};

View File

@ -0,0 +1,18 @@
#ifndef __CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY_HEADER__
#define __CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY_HEADER__
#define CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY_VENDOR 0
#define CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY_TYPE 1032
#define CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY_VENDOR, .type = CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY_TYPE }
struct capwap_80211_multidomaincapability_element {
uint8_t radioid;
uint16_t firstchannel;
uint16_t numberchannels;
uint16_t maxtxpowerlevel;
};
extern const struct capwap_message_elements_ops capwap_element_80211_multidomaincapability_ops;
#endif /* __CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY_HEADER__ */

View File

@ -0,0 +1,81 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Reserved | Current Chan | Band Support |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TI Threshold |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1033 for IEEE 802.11 OFDM Control
Length: 8
********************************************************************/
/* */
static void capwap_80211_ofdmcontrol_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_ofdmcontrol_element* element = (struct capwap_80211_ofdmcontrol_element*)data;
ASSERT(data != NULL);
/* */
func->write_u8(handle, element->radioid);
func->write_u8(handle, 0);
func->write_u8(handle, element->currentchannel);
func->write_u8(handle, element->bandsupport);
func->write_u32(handle, element->tithreshold);
}
/* */
static void* capwap_80211_ofdmcontrol_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_80211_ofdmcontrol_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 8) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 OFDM Control element");
return NULL;
}
/* */
data = (struct capwap_80211_ofdmcontrol_element*)capwap_alloc(sizeof(struct capwap_80211_ofdmcontrol_element));
memset(data, 0, sizeof(struct capwap_80211_ofdmcontrol_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, NULL);
func->read_u8(handle, &data->currentchannel);
func->read_u8(handle, &data->bandsupport);
func->read_u32(handle, &data->tithreshold);
return data;
}
/* */
static void* capwap_80211_ofdmcontrol_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_ofdmcontrol_element));
}
/* */
static void capwap_80211_ofdmcontrol_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_ofdmcontrol_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211_ofdmcontrol_element_create,
.parse = capwap_80211_ofdmcontrol_element_parsing,
.clone = capwap_80211_ofdmcontrol_element_clone,
.free = capwap_80211_ofdmcontrol_element_free
};

View File

@ -0,0 +1,27 @@
#ifndef __CAPWAP_ELEMENT_80211_OFDMCONTROL_HEADER__
#define __CAPWAP_ELEMENT_80211_OFDMCONTROL_HEADER__
#define CAPWAP_ELEMENT_80211_OFDMCONTROL_VENDOR 0
#define CAPWAP_ELEMENT_80211_OFDMCONTROL_TYPE 1033
#define CAPWAP_ELEMENT_80211_OFDMCONTROL (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_OFDMCONTROL_VENDOR, .type = CAPWAP_ELEMENT_80211_OFDMCONTROL_TYPE }
#define CAPWAP_OFDMCONTROL_BAND_515_525 0x01
#define CAPWAP_OFDMCONTROL_BAND_525_535 0x02
#define CAPWAP_OFDMCONTROL_BAND_5725_5825 0x04
#define CAPWAP_OFDMCONTROL_BAND_547_5725 0x08
#define CAPWAP_OFDMCONTROL_BAND_JP_525 0x10
#define CAPWAP_OFDMCONTROL_BAND_503_5091 0x20
#define CAPWAP_OFDMCONTROL_BAND_494_499 0x40
#define CAPWAP_OFDMCONTROL_BAND_MASK 0x7f
struct capwap_80211_ofdmcontrol_element {
uint8_t radioid;
uint8_t currentchannel;
uint8_t bandsupport;
uint32_t tithreshold;
};
extern const struct capwap_message_elements_ops capwap_element_80211_ofdmcontrol_ops;
#endif /* __CAPWAP_ELEMENT_80211_OFDMCONTROL_HEADER__ */

View File

@ -0,0 +1,81 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Rate Set...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1034 for IEEE 802.11 Rate Set
Length: >= 3
********************************************************************/
/* */
static void capwap_80211_rateset_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_rateset_element* element = (struct capwap_80211_rateset_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_block(handle, element->rateset, element->ratesetcount);
}
/* */
static void* capwap_80211_rateset_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
unsigned short length;
struct capwap_80211_rateset_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 3) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Rate Set element");
return NULL;
}
length -= 1;
if (length > CAPWAP_RATESET_MAXLENGTH) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Rate Set element");
return NULL;
}
/* */
data = (struct capwap_80211_rateset_element*)capwap_alloc(sizeof(struct capwap_80211_rateset_element));
memset(data, 0, sizeof(struct capwap_80211_rateset_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
data->ratesetcount = length;
func->read_block(handle, data->rateset, length);
return data;
}
/* */
static void* capwap_80211_rateset_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_rateset_element));
}
/* */
static void capwap_80211_rateset_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_rateset_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211_rateset_element_create,
.parse = capwap_80211_rateset_element_parsing,
.clone = capwap_80211_rateset_element_clone,
.free = capwap_80211_rateset_element_free
};

View File

@ -0,0 +1,20 @@
#ifndef __CAPWAP_ELEMENT_80211_RATESET_HEADER__
#define __CAPWAP_ELEMENT_80211_RATESET_HEADER__
#define CAPWAP_ELEMENT_80211_RATESET_VENDOR 0
#define CAPWAP_ELEMENT_80211_RATESET_TYPE 1034
#define CAPWAP_ELEMENT_80211_RATESET (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_RATESET_VENDOR, .type = CAPWAP_ELEMENT_80211_RATESET_TYPE }
#define CAPWAP_RATESET_MINLENGTH 2
#define CAPWAP_RATESET_MAXLENGTH 8
struct capwap_80211_rateset_element {
uint8_t radioid;
uint8_t ratesetcount;
uint8_t rateset[CAPWAP_RATESET_MAXLENGTH];
};
extern const struct capwap_message_elements_ops capwap_element_80211_rateset_ops;
#endif /* __CAPWAP_ELEMENT_80211_RATESET_HEADER__ */

View File

@ -0,0 +1,109 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Client MAC Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Client MAC Address | BSSID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BSSID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | WLAN ID | Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TKIP ICV Errors |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TKIP Local MIC Failures |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TKIP Remote MIC Failures |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| CCMP Replays |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| CCMP Decrypt Errors |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TKIP Replays |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1035 for IEEE 802.11 RSNA Error Report From Station
Length: 40
********************************************************************/
/* */
static void capwap_80211_rsnaerrorreport_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_rsnaerrorreport_element* element = (struct capwap_80211_rsnaerrorreport_element*)data;
ASSERT(data != NULL);
func->write_block(handle, element->client, MACADDRESS_EUI48_LENGTH);
func->write_block(handle, element->bssid, MACADDRESS_EUI48_LENGTH);
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->wlanid);
func->write_u16(handle, 0);
func->write_u32(handle, element->tkipicverrors);
func->write_u32(handle, element->tkiplocalmicfailure);
func->write_u32(handle, element->tkipremotemicfailure);
func->write_u32(handle, element->ccmpreplays);
func->write_u32(handle, element->ccmpdecrypterrors);
func->write_u32(handle, element->tkipreplays);
}
/* */
static void* capwap_80211_rsnaerrorreport_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_80211_rsnaerrorreport_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 40) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 RSNA Error Report From Station element");
return NULL;
}
/* */
data = (struct capwap_80211_rsnaerrorreport_element*)capwap_alloc(sizeof(struct capwap_80211_rsnaerrorreport_element));
memset(data, 0, sizeof(struct capwap_80211_rsnaerrorreport_element));
/* Retrieve data */
func->read_block(handle, data->client, MACADDRESS_EUI48_LENGTH);
func->read_block(handle, data->bssid, MACADDRESS_EUI48_LENGTH);
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->wlanid);
func->read_u16(handle, NULL);
func->read_u32(handle, &data->tkipicverrors);
func->read_u32(handle, &data->tkiplocalmicfailure);
func->read_u32(handle, &data->tkipremotemicfailure);
func->read_u32(handle, &data->ccmpreplays);
func->read_u32(handle, &data->ccmpdecrypterrors);
func->read_u32(handle, &data->tkipreplays);
return data;
}
/* */
static void* capwap_80211_rsnaerrorreport_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_rsnaerrorreport_element));
}
/* */
static void capwap_80211_rsnaerrorreport_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_rsnaerrorreport_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_80211_rsnaerrorreport_element_create,
.parse = capwap_80211_rsnaerrorreport_element_parsing,
.clone = capwap_80211_rsnaerrorreport_element_clone,
.free = capwap_80211_rsnaerrorreport_element_free
};

View File

@ -0,0 +1,24 @@
#ifndef __CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT_HEADER__
#define __CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT_HEADER__
#define CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT_VENDOR 0
#define CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT_TYPE 1035
#define CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT_VENDOR, .type = CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT_TYPE }
struct capwap_80211_rsnaerrorreport_element {
uint8_t client[MACADDRESS_EUI48_LENGTH];
uint8_t bssid[MACADDRESS_EUI48_LENGTH];
uint8_t radioid;
uint8_t wlanid;
uint32_t tkipicverrors;
uint32_t tkiplocalmicfailure;
uint32_t tkipremotemicfailure;
uint32_t ccmpreplays;
uint32_t ccmpdecrypterrors;
uint32_t tkipreplays;
};
extern const struct capwap_message_elements_ops capwap_element_80211_rsnaerrorreport_ops;
#endif /* __CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT_HEADER__ */

View File

@ -0,0 +1,97 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Association ID | Flags |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| MAC Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| MAC Address | Capabilities |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| WLAN ID |Supported Rates|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1036 for IEEE 802.11 Station
Length: >= 14
********************************************************************/
/* */
static void capwap_80211_station_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_station_element* element = (struct capwap_80211_station_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_u16(handle, element->associationid);
func->write_u8(handle, element->flags);
func->write_block(handle, element->address, MACADDRESS_EUI48_LENGTH);
func->write_u16(handle, element->capabilities);
func->write_u8(handle, element->wlanid);
func->write_block(handle, element->supportedrates, element->supportedratescount);
}
/* */
static void* capwap_80211_station_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
unsigned short length;
struct capwap_80211_station_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 14) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Station element");
return NULL;
}
length -= 13;
if (length > CAPWAP_STATION_RATES_MAXLENGTH) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Station element");
return NULL;
}
/* */
data = (struct capwap_80211_station_element*)capwap_alloc(sizeof(struct capwap_80211_station_element));
memset(data, 0, sizeof(struct capwap_80211_station_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u16(handle, &data->associationid);
func->read_u8(handle, &data->flags);
func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH);
func->read_u16(handle, &data->capabilities);
func->read_u8(handle, &data->wlanid);
data->supportedratescount = length;
func->read_block(handle, data->supportedrates, length);
return data;
}
/* */
static void* capwap_80211_station_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_station_element));
}
/* */
static void capwap_80211_station_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_station_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_80211_station_element_create,
.parse = capwap_80211_station_element_parsing,
.clone = capwap_80211_station_element_clone,
.free = capwap_80211_station_element_free
};

View File

@ -0,0 +1,24 @@
#ifndef __CAPWAP_ELEMENT_80211_STATION_HEADER__
#define __CAPWAP_ELEMENT_80211_STATION_HEADER__
#define CAPWAP_ELEMENT_80211_STATION_VENDOR 0
#define CAPWAP_ELEMENT_80211_STATION_TYPE 1036
#define CAPWAP_ELEMENT_80211_STATION (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_STATION_VENDOR, .type = CAPWAP_ELEMENT_80211_STATION_TYPE }
#define CAPWAP_STATION_RATES_MAXLENGTH 128
struct capwap_80211_station_element {
uint8_t radioid;
uint16_t associationid;
uint8_t flags;
uint8_t address[MACADDRESS_EUI48_LENGTH];
uint16_t capabilities;
uint8_t wlanid;
uint8_t supportedratescount;
uint8_t supportedrates[CAPWAP_STATION_RATES_MAXLENGTH];
};
extern const struct capwap_message_elements_ops capwap_element_80211_station_ops;
#endif /* __CAPWAP_ELEMENT_80211_STATION_HEADER__ */

View File

@ -0,0 +1,108 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| MAC Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| MAC Address |A|C| Flags |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Pairwise TSC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Pairwise TSC | Pairwise RSC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Pairwise RSC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Key...
+-+-+-+-+-+-+-+-
Type: 1038 for IEEE 802.11 Station Session Key
Length: >= 25
********************************************************************/
/* */
static void capwap_80211_stationkey_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_stationkey_element* element = (struct capwap_80211_stationkey_element*)data;
ASSERT(data != NULL);
func->write_block(handle, element->address, MACADDRESS_EUI48_LENGTH);
func->write_u16(handle, element->flags);
func->write_block(handle, element->pairwisetsc, CAPWAP_STATION_SESSION_KEY_PAIRWISE_TSC_LENGTH);
func->write_block(handle, element->pairwisersc, CAPWAP_STATION_SESSION_KEY_PAIRWISE_RSC_LENGTH);
func->write_block(handle, element->key, element->keylength);
}
/* */
static void* capwap_80211_stationkey_element_parsing(capwap_message_elements_handle handle,
struct capwap_read_message_elements_ops* func)
{
unsigned short length;
struct capwap_80211_stationkey_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 25) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Station Session Key element");
return NULL;
}
/* */
data = (struct capwap_80211_stationkey_element *)
capwap_alloc(sizeof(struct capwap_80211_stationkey_element));
memset(data, 0, sizeof(struct capwap_80211_stationkey_element));
data->keylength = length - 20;
data->key = (uint8_t*)capwap_alloc(data->keylength);
/* Retrieve data */
func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH);
func->read_u16(handle, &data->flags);
func->read_block(handle, data->pairwisetsc, CAPWAP_STATION_SESSION_KEY_PAIRWISE_TSC_LENGTH);
func->read_block(handle, data->pairwisersc, CAPWAP_STATION_SESSION_KEY_PAIRWISE_RSC_LENGTH);
func->read_block(handle, data->key, data->keylength);
return data;
}
/* */
static void* capwap_80211_stationkey_element_clone(void* data) {
struct capwap_80211_stationkey_element* cloneelement;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_80211_stationkey_element));
if (cloneelement->keylength > 0) {
cloneelement->key = capwap_clone(((struct capwap_80211_stationkey_element*)data)->key, cloneelement->keylength);
}
return cloneelement;
}
/* */
static void capwap_80211_stationkey_element_free(void* data) {
struct capwap_80211_stationkey_element* element = (struct capwap_80211_stationkey_element*)data;
ASSERT(data != NULL);
if (element->key) {
capwap_free(element->key);
}
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_stationkey_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_80211_stationkey_element_create,
.parse = capwap_80211_stationkey_element_parsing,
.clone = capwap_80211_stationkey_element_clone,
.free = capwap_80211_stationkey_element_free
};

View File

@ -0,0 +1,26 @@
#ifndef __CAPWAP_ELEMENT_80211_STATION_SESSION_KEY_HEADER__
#define __CAPWAP_ELEMENT_80211_STATION_SESSION_KEY_HEADER__
#define CAPWAP_ELEMENT_80211_STATION_SESSION_KEY_PROFILE_VENDOR 0
#define CAPWAP_ELEMENT_80211_STATION_SESSION_KEY_PROFILE_TYPE 1038
#define CAPWAP_ELEMENT_80211_STATION_SESSION_KEY_PROFILE (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_STATION_SESSION_KEY_PROFILE_VENDOR, .type = CAPWAP_ELEMENT_80211_STATION_SESSION_KEY_PROFILE_TYPE }
#define CAPWAP_STATION_SESSION_KEY_PAIRWISE_TSC_LENGTH 6
#define CAPWAP_STATION_SESSION_KEY_PAIRWISE_RSC_LENGTH 6
#define CAPWAP_STATION_SESSION_KEY_AKM_ONLY 0x8000
#define CAPWAP_STATION_SESSION_KEY_AC_ENCRYPT 0x4000
struct capwap_80211_stationkey_element {
uint8_t address[MACADDRESS_EUI48_LENGTH];
uint16_t flags;
uint8_t pairwisetsc[CAPWAP_STATION_SESSION_KEY_PAIRWISE_TSC_LENGTH];
uint8_t pairwisersc[CAPWAP_STATION_SESSION_KEY_PAIRWISE_RSC_LENGTH];
uint16_t keylength;
uint8_t* key;
};
extern const struct capwap_message_elements_ops capwap_element_80211_stationkey_ops;
#endif /* __CAPWAP_ELEMENT_80211_STATION_SESSION_KEY_HEADER__ */

View File

@ -0,0 +1,76 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| MAC Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| MAC Address | Reserved |8021p|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1037 for IEEE 802.11 Station QoS Profile
Length: 8
********************************************************************/
/* */
static void capwap_80211_stationqos_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_stationqos_element* element = (struct capwap_80211_stationqos_element*)data;
ASSERT(data != NULL);
func->write_block(handle, element->address, MACADDRESS_EUI48_LENGTH);
func->write_u8(handle, 0);
func->write_u8(handle, element->priority);
}
/* */
static void* capwap_80211_stationqos_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_80211_stationqos_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 8) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Station QoS Profile element");
return NULL;
}
/* */
data = (struct capwap_80211_stationqos_element*)capwap_alloc(sizeof(struct capwap_80211_stationqos_element));
memset(data, 0, sizeof(struct capwap_80211_stationqos_element));
/* Retrieve data */
func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH);
func->read_u8(handle, NULL);
func->read_u8(handle, &data->priority);
return data;
}
/* */
static void* capwap_80211_stationqos_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_stationqos_element));
}
/* */
static void capwap_80211_stationqos_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_stationqos_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_80211_stationqos_element_create,
.parse = capwap_80211_stationqos_element_parsing,
.clone = capwap_80211_stationqos_element_clone,
.free = capwap_80211_stationqos_element_free
};

View File

@ -0,0 +1,16 @@
#ifndef __CAPWAP_ELEMENT_80211_STATION_QOS_PROFILE_HEADER__
#define __CAPWAP_ELEMENT_80211_STATION_QOS_PROFILE_HEADER__
#define CAPWAP_ELEMENT_80211_STATION_QOS_PROFILE_VENDOR 0
#define CAPWAP_ELEMENT_80211_STATION_QOS_PROFILE_TYPE 1037
#define CAPWAP_ELEMENT_80211_STATION_QOS_PROFILE (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_STATION_QOS_PROFILE_VENDOR, .type = CAPWAP_ELEMENT_80211_STATION_QOS_PROFILE_TYPE }
struct capwap_80211_stationqos_element {
uint8_t address[MACADDRESS_EUI48_LENGTH];
uint8_t priority;
};
extern const struct capwap_message_elements_ops capwap_element_80211_stationqos_ops;
#endif /* __CAPWAP_ELEMENT_80211_STATION_QOS_PROFILE_HEADER__ */

View File

@ -0,0 +1,149 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Tx Fragment Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Multicast Tx Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Failed Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Retry Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Multiple Retry Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Frame Duplicate Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RTS Success Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RTS Failure Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ACK Failure Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Rx Fragment Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Multicast RX Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| FCS Error Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Tx Frame Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Decryption Errors |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Discarded QoS Fragment Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Associated Station Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| QoS CF Polls Received Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| QoS CF Polls Unused Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| QoS CF Polls Unusable Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1039 for IEEE 802.11 Statistics
Length: 80
********************************************************************/
/* */
static void capwap_80211_statistics_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_statistics_element* element = (struct capwap_80211_statistics_element*)data;
ASSERT(data != NULL);
/* */
func->write_u8(handle, element->radioid);
func->write_block(handle, NULL, 3);
func->write_u32(handle, element->txfragment);
func->write_u32(handle, element->multicasttx);
func->write_u32(handle, element->failed);
func->write_u32(handle, element->retry);
func->write_u32(handle, element->multipleretry);
func->write_u32(handle, element->frameduplicate);
func->write_u32(handle, element->rtssuccess);
func->write_u32(handle, element->rtsfailure);
func->write_u32(handle, element->ackfailure);
func->write_u32(handle, element->rxfragment);
func->write_u32(handle, element->multicastrx);
func->write_u32(handle, element->fcserror);
func->write_u32(handle, element->txframe);
func->write_u32(handle, element->decryptionerror);
func->write_u32(handle, element->discardedqosfragment);
func->write_u32(handle, element->associatedstation);
func->write_u32(handle, element->qoscfpollsreceived);
func->write_u32(handle, element->qoscfpollsunused);
func->write_u32(handle, element->qoscfpollsunusable);
}
/* */
static void* capwap_80211_statistics_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_80211_statistics_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 80) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Statistics element");
return NULL;
}
/* */
data = (struct capwap_80211_statistics_element*)capwap_alloc(sizeof(struct capwap_80211_statistics_element));
memset(data, 0, sizeof(struct capwap_80211_statistics_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_block(handle, NULL, 3);
func->read_u32(handle, &data->txfragment);
func->read_u32(handle, &data->multicasttx);
func->read_u32(handle, &data->failed);
func->read_u32(handle, &data->retry);
func->read_u32(handle, &data->multipleretry);
func->read_u32(handle, &data->frameduplicate);
func->read_u32(handle, &data->rtssuccess);
func->read_u32(handle, &data->rtsfailure);
func->read_u32(handle, &data->ackfailure);
func->read_u32(handle, &data->rxfragment);
func->read_u32(handle, &data->multicastrx);
func->read_u32(handle, &data->fcserror);
func->read_u32(handle, &data->txframe);
func->read_u32(handle, &data->decryptionerror);
func->read_u32(handle, &data->discardedqosfragment);
func->read_u32(handle, &data->associatedstation);
func->read_u32(handle, &data->qoscfpollsreceived);
func->read_u32(handle, &data->qoscfpollsunused);
func->read_u32(handle, &data->qoscfpollsunusable);
return data;
}
/* */
static void* capwap_80211_statistics_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_statistics_element));
}
/* */
static void capwap_80211_statistics_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_statistics_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211_statistics_element_create,
.parse = capwap_80211_statistics_element_parsing,
.clone = capwap_80211_statistics_element_clone,
.free = capwap_80211_statistics_element_free
};

View File

@ -0,0 +1,34 @@
#ifndef __CAPWAP_ELEMENT_80211_STATISTICS_HEADER__
#define __CAPWAP_ELEMENT_80211_STATISTICS_HEADER__
#define CAPWAP_ELEMENT_80211_STATISTICS_VENDOR 0
#define CAPWAP_ELEMENT_80211_STATISTICS_TYPE 1039
#define CAPWAP_ELEMENT_80211_STATISTICS (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_STATISTICS_VENDOR, .type = CAPWAP_ELEMENT_80211_STATISTICS_TYPE }
struct capwap_80211_statistics_element {
uint8_t radioid;
uint32_t txfragment;
uint32_t multicasttx;
uint32_t failed;
uint32_t retry;
uint32_t multipleretry;
uint32_t frameduplicate;
uint32_t rtssuccess;
uint32_t rtsfailure;
uint32_t ackfailure;
uint32_t rxfragment;
uint32_t multicastrx;
uint32_t fcserror;
uint32_t txframe;
uint32_t decryptionerror;
uint32_t discardedqosfragment;
uint32_t associatedstation;
uint32_t qoscfpollsreceived;
uint32_t qoscfpollsunused;
uint32_t qoscfpollsunusable;
};
extern const struct capwap_message_elements_ops capwap_element_80211_statistics_ops;
#endif /* __CAPWAP_ELEMENT_80211_STATISTICS_HEADER__ */

View File

@ -0,0 +1,102 @@
#include "capwap.h"
#include "element.h"
/*
* The IEEE 802.11 Supported MAC Profile message element allows the WTP
* to communicate the profiles it supports. The Discovery Request
* message, Primary Discovery Request message, and Join Request message
* may include one such message element.
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0
* +=+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
* | Num_Profiles | Profile_1 | Profile_[2..N]..
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
*
* o Type: 1060 for IEEE 802.11 Supported MAC Profiles
*
* o Num_Profiles >=1: This refers to the number of profiles present in
* this message element. There must be at least one profile.
*
* o Profile: Each profile is identified by a value specified in
* Section 3.2.
*/
/* */
static void
capwap_80211_supported_mac_profiles_element_create(void *data, capwap_message_elements_handle handle,
struct capwap_write_message_elements_ops *func)
{
struct capwap_80211_supported_mac_profiles_element *element =
(struct capwap_80211_supported_mac_profiles_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->supported_mac_profilescount);
func->write_block(handle, element->supported_mac_profiles, element->supported_mac_profilescount);
}
/* */
static void *
capwap_80211_supported_mac_profiles_element_parsing(capwap_message_elements_handle handle,
struct capwap_read_message_elements_ops *func)
{
unsigned short length;
struct capwap_80211_supported_mac_profiles_element *data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 1 || length > 255) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Supported MAC Profiles element");
return NULL;
}
length -= 1;
/* */
data = (struct capwap_80211_supported_mac_profiles_element *)
capwap_alloc(sizeof(struct capwap_80211_supported_mac_profiles_element) + length);
memset(data, 0, sizeof(struct capwap_80211_supported_mac_profiles_element) + length);
/* Retrieve data */
func->read_u8(handle, &data->supported_mac_profilescount);
if (data->supported_mac_profilescount != length) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Supported MAC Profiles element");
capwap_free(data);
return NULL;
}
func->read_block(handle, data->supported_mac_profiles, length);
return data;
}
/* */
static void *capwap_80211_supported_mac_profiles_element_clone(void *data)
{
struct capwap_80211_supported_mac_profiles_element *element =
(struct capwap_80211_supported_mac_profiles_element*)data;
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_supported_mac_profiles_element)
+ element->supported_mac_profilescount);
}
/* */
static void capwap_80211_supported_mac_profiles_element_free(void *data)
{
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_supported_mac_profiles_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_80211_supported_mac_profiles_element_create,
.parse = capwap_80211_supported_mac_profiles_element_parsing,
.clone = capwap_80211_supported_mac_profiles_element_clone,
.free = capwap_80211_supported_mac_profiles_element_free
};

View File

@ -0,0 +1,20 @@
#ifndef __CAPWAP_ELEMENT_80211_SUPPORTED_MAC_PROFILES_HEADER__
#define __CAPWAP_ELEMENT_80211_SUPPORTED_MAC_PROFILES_HEADER__
#define CAPWAP_ELEMENT_80211_SUPPORTED_MAC_PROFILES_VENDOR 0
#define CAPWAP_ELEMENT_80211_SUPPORTED_MAC_PROFILES_TYPE 1060
#define CAPWAP_ELEMENT_80211_SUPPORTED_MAC_PROFILES \
(struct capwap_message_element_id) { \
.vendor = CAPWAP_ELEMENT_80211_SUPPORTED_MAC_PROFILES_VENDOR, \
.type = CAPWAP_ELEMENT_80211_SUPPORTED_MAC_PROFILES_TYPE \
}
struct capwap_80211_supported_mac_profiles_element {
uint8_t supported_mac_profilescount;
uint8_t supported_mac_profiles[];
};
extern const struct capwap_message_elements_ops capwap_element_80211_supported_mac_profiles_ops;
#endif /* __CAPWAP_ELEMENT_80211_SUPPORTED_MAC_PROFILES_HEADER__ */

View File

@ -0,0 +1,81 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Supported Rates...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1040 for IEEE 802.11 Supported Rates
Length: >= 3
********************************************************************/
/* */
static void capwap_80211_supportedrates_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_supportedrates_element* element = (struct capwap_80211_supportedrates_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_block(handle, element->supportedrates, element->supportedratescount);
}
/* */
static void* capwap_80211_supportedrates_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
unsigned short length;
struct capwap_80211_supportedrates_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 3) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Supported Rates element");
return NULL;
}
length -= 1;
if (length > CAPWAP_RATESET_MAXLENGTH) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Supported Rates element");
return NULL;
}
/* */
data = (struct capwap_80211_supportedrates_element*)capwap_alloc(sizeof(struct capwap_80211_supportedrates_element));
memset(data, 0, sizeof(struct capwap_80211_supportedrates_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
data->supportedratescount = length;
func->read_block(handle, data->supportedrates, length);
return data;
}
/* */
static void* capwap_80211_supportedrates_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_supportedrates_element));
}
/* */
static void capwap_80211_supportedrates_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_supportedrates_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211_supportedrates_element_create,
.parse = capwap_80211_supportedrates_element_parsing,
.clone = capwap_80211_supportedrates_element_clone,
.free = capwap_80211_supportedrates_element_free
};

View File

@ -0,0 +1,20 @@
#ifndef __CAPWAP_ELEMENT_80211_SUPPORTEDRATES_HEADER__
#define __CAPWAP_ELEMENT_80211_SUPPORTEDRATES_HEADER__
#define CAPWAP_ELEMENT_80211_SUPPORTEDRATES_VENDOR 0
#define CAPWAP_ELEMENT_80211_SUPPORTEDRATES_TYPE 1040
#define CAPWAP_ELEMENT_80211_SUPPORTEDRATES (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_SUPPORTEDRATES_VENDOR, .type = CAPWAP_ELEMENT_80211_SUPPORTEDRATES_TYPE }
#define CAPWAP_SUPPORTEDRATES_MINLENGTH 2
#define CAPWAP_SUPPORTEDRATES_MAXLENGTH 8
struct capwap_80211_supportedrates_element {
uint8_t radioid;
uint8_t supportedratescount;
uint8_t supportedrates[CAPWAP_SUPPORTEDRATES_MAXLENGTH];
};
extern const struct capwap_message_elements_ops capwap_element_80211_supportedrates_ops;
#endif /* __CAPWAP_ELEMENT_80211_SUPPORTEDRATES_HEADER__ */

View File

@ -0,0 +1,75 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Reserved | Current Tx Power |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1041 for IEEE 802.11 Tx Power
Length: 4
********************************************************************/
/* */
static void capwap_80211_txpower_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_txpower_element* element = (struct capwap_80211_txpower_element*)data;
ASSERT(data != NULL);
/* */
func->write_u8(handle, element->radioid);
func->write_u8(handle, 0);
func->write_u16(handle, element->currenttxpower);
}
/* */
static void* capwap_80211_txpower_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_80211_txpower_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 4) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Tx Power element");
return NULL;
}
/* */
data = (struct capwap_80211_txpower_element*)capwap_alloc(sizeof(struct capwap_80211_txpower_element));
memset(data, 0, sizeof(struct capwap_80211_txpower_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, NULL);
func->read_u16(handle, &data->currenttxpower);
return data;
}
/* */
static void* capwap_80211_txpower_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_txpower_element));
}
/* */
static void capwap_80211_txpower_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_txpower_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211_txpower_element_create,
.parse = capwap_80211_txpower_element_parsing,
.clone = capwap_80211_txpower_element_clone,
.free = capwap_80211_txpower_element_free
};

View File

@ -0,0 +1,16 @@
#ifndef __CAPWAP_ELEMENT_80211_TXPOWER_HEADER__
#define __CAPWAP_ELEMENT_80211_TXPOWER_HEADER__
#define CAPWAP_ELEMENT_80211_TXPOWER_VENDOR 0
#define CAPWAP_ELEMENT_80211_TXPOWER_TYPE 1041
#define CAPWAP_ELEMENT_80211_TXPOWER (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_TXPOWER_VENDOR, .type = CAPWAP_ELEMENT_80211_TXPOWER_TYPE }
struct capwap_80211_txpower_element {
uint8_t radioid;
uint16_t currenttxpower;
};
extern const struct capwap_message_elements_ops capwap_element_80211_txpower_ops;
#endif /* __CAPWAP_ELEMENT_80211_TXPOWER_HEADER__ */

View File

@ -0,0 +1,96 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Num Levels | Power Level [n] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1042 for IEEE 802.11 Tx Power Level
Length: >= 4
********************************************************************/
/* */
static void capwap_80211_txpowerlevel_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
int i;
struct capwap_80211_txpowerlevel_element* element = (struct capwap_80211_txpowerlevel_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->numlevels);
for (i = 0; i < element->numlevels; i++) {
func->write_u16(handle, element->powerlevel[i]);
}
}
/* */
static void* capwap_80211_txpowerlevel_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
int i;
unsigned short length;
struct capwap_80211_txpowerlevel_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 4) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Tx Power Level element");
return NULL;
}
length -= 2;
if ((length % sizeof(uint16_t)) || ((length / sizeof(uint16_t)) > CAPWAP_TXPOWERLEVEL_MAXLENGTH)) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Tx Power Level element");
return NULL;
}
/* */
data = (struct capwap_80211_txpowerlevel_element*)capwap_alloc(sizeof(struct capwap_80211_txpowerlevel_element));
memset(data, 0, sizeof(struct capwap_80211_txpowerlevel_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->numlevels);
/* Check */
if ((data->numlevels * sizeof(uint16_t)) != length) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Tx Power Level element");
capwap_free(data);
return NULL;
}
for (i = 0; i < data->numlevels; i++) {
func->read_u16(handle, &data->powerlevel[i]);
}
return data;
}
/* */
static void* capwap_80211_txpowerlevel_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_txpowerlevel_element));
}
/* */
static void capwap_80211_txpowerlevel_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_txpowerlevel_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211_txpowerlevel_element_create,
.parse = capwap_80211_txpowerlevel_element_parsing,
.clone = capwap_80211_txpowerlevel_element_clone,
.free = capwap_80211_txpowerlevel_element_free
};

View File

@ -0,0 +1,19 @@
#ifndef __CAPWAP_ELEMENT_80211_TXPOWERLEVEL_HEADER__
#define __CAPWAP_ELEMENT_80211_TXPOWERLEVEL_HEADER__
#define CAPWAP_ELEMENT_80211_TXPOWERLEVEL_VENDOR 0
#define CAPWAP_ELEMENT_80211_TXPOWERLEVEL_TYPE 1042
#define CAPWAP_ELEMENT_80211_TXPOWERLEVEL (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_TXPOWERLEVEL_VENDOR, .type = CAPWAP_ELEMENT_80211_TXPOWERLEVEL_TYPE }
#define CAPWAP_TXPOWERLEVEL_MAXLENGTH 8
struct capwap_80211_txpowerlevel_element {
uint8_t radioid;
uint8_t numlevels;
uint16_t powerlevel[CAPWAP_TXPOWERLEVEL_MAXLENGTH];
};
extern const struct capwap_message_elements_ops capwap_element_80211_txpowerlevel_ops;
#endif /* __CAPWAP_ELEMENT_80211_TXPOWERLEVEL_HEADER__ */

View File

@ -0,0 +1,92 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | MAC Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| MAC Address | QoS Sub-Element... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved|8021p|RSV| DSCP Tag |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1043 for IEEE 802.11 Update Station QoS
Length: 14
********************************************************************/
/* */
static void capwap_80211_updatestationqos_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
int i;
struct capwap_80211_updatestationqos_element* element = (struct capwap_80211_updatestationqos_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_block(handle, element->address, MACADDRESS_EUI48_LENGTH);
for (i = 0; i < CAPWAP_UPDATE_STATION_QOS_SUBELEMENTS; i++) {
func->write_u8(handle, element->qos[i].priority8021p & CAPWAP_UPDATE_STATION_QOS_PRIORIY_MASK);
func->write_u8(handle, element->qos[i].dscp & CAPWAP_UPDATE_STATION_QOS_DSCP_MASK);
}
}
/* */
static void* capwap_80211_updatestationqos_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
int i;
struct capwap_80211_updatestationqos_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 14) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Update Station QoS element");
return NULL;
}
/* */
data = (struct capwap_80211_updatestationqos_element*)capwap_alloc(sizeof(struct capwap_80211_updatestationqos_element));
memset(data, 0, sizeof(struct capwap_80211_updatestationqos_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH);
for (i = 0; i < CAPWAP_UPDATE_STATION_QOS_SUBELEMENTS; i++) {
func->read_u8(handle, &data->qos[i].priority8021p);
data->qos[i].priority8021p &= CAPWAP_UPDATE_STATION_QOS_PRIORIY_MASK;
func->read_u8(handle, &data->qos[i].dscp);
data->qos[i].dscp &= CAPWAP_UPDATE_STATION_QOS_DSCP_MASK;
}
return data;
}
/* */
static void* capwap_80211_updatestationqos_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_updatestationqos_element));
}
/* */
static void capwap_80211_updatestationqos_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_updatestationqos_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_80211_updatestationqos_element_create,
.parse = capwap_80211_updatestationqos_element_parsing,
.clone = capwap_80211_updatestationqos_element_clone,
.free = capwap_80211_updatestationqos_element_free
};

View File

@ -0,0 +1,27 @@
#ifndef __CAPWAP_ELEMENT_80211_UPDATE_STATION_QOS_HEADER__
#define __CAPWAP_ELEMENT_80211_UPDATE_STATION_QOS_HEADER__
#define CAPWAP_ELEMENT_80211_UPDATE_STATION_QOS_VENDOR 0
#define CAPWAP_ELEMENT_80211_UPDATE_STATION_QOS_TYPE 1043
#define CAPWAP_ELEMENT_80211_UPDATE_STATION_QOS (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_UPDATE_STATION_QOS_VENDOR, .type = CAPWAP_ELEMENT_80211_UPDATE_STATION_QOS_TYPE }
#define CAPWAP_UPDATE_STATION_QOS_SUBELEMENTS 4
#define CAPWAP_UPDATE_STATION_QOS_PRIORIY_MASK 0x07
#define CAPWAP_UPDATE_STATION_QOS_DSCP_MASK 0x3f
struct capwap_80211_updatestationqos_subelement {
uint8_t priority8021p;
uint8_t dscp;
};
struct capwap_80211_updatestationqos_element {
uint8_t radioid;
uint8_t address[MACADDRESS_EUI48_LENGTH];
struct capwap_80211_updatestationqos_subelement qos[CAPWAP_UPDATE_STATION_QOS_SUBELEMENTS];
};
extern const struct capwap_message_elements_ops capwap_element_80211_updatestationqos_ops;
#endif /* __CAPWAP_ELEMENT_80211_UPDATE_STATION_QOS_HEADER__ */

View File

@ -0,0 +1,113 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | WLAN ID | Capability |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Key Index | Key Status | Key Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Key... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1044 for IEEE 802.11 Update WLAN
Length: >= 8
********************************************************************/
/* */
static void capwap_80211_updatewlan_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_updatewlan_element* element = (struct capwap_80211_updatewlan_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->wlanid);
func->write_u16(handle, element->capability);
func->write_u8(handle, element->keyindex);
func->write_u8(handle, element->keystatus);
func->write_u16(handle, element->keylength);
if ((element->keylength > 0) && element->key) {
func->write_block(handle, element->key, element->keylength);
}
}
/* */
static void* capwap_80211_updatewlan_element_clone(void* data) {
struct capwap_80211_updatewlan_element* cloneelement;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_80211_updatewlan_element));
if (cloneelement->keylength > 0) {
cloneelement->key = capwap_clone(((struct capwap_80211_updatewlan_element*)data)->key, cloneelement->keylength);
}
return cloneelement;
}
/* */
static void capwap_80211_updatewlan_element_free(void* data) {
struct capwap_80211_updatewlan_element* element = (struct capwap_80211_updatewlan_element*)data;
ASSERT(data != NULL);
if (element->key) {
capwap_free(element->key);
}
capwap_free(data);
}
/* */
static void* capwap_80211_updatewlan_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
unsigned short length;
struct capwap_80211_updatewlan_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 8) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Update WLAN element");
return NULL;
}
length -= 8;
/* */
data = (struct capwap_80211_updatewlan_element*)capwap_alloc(sizeof(struct capwap_80211_updatewlan_element));
memset(data, 0, sizeof(struct capwap_80211_updatewlan_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->wlanid);
func->read_u16(handle, &data->capability);
func->read_u8(handle, &data->keyindex);
func->read_u8(handle, &data->keystatus);
func->read_u16(handle, &data->keylength);
if (length != data->keylength) {
capwap_80211_updatewlan_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 Update WLAN element");
return NULL;
} else if (data->keylength > 0) {
data->key = (uint8_t*)capwap_alloc(data->keylength);
func->read_block(handle, data->key, data->keylength);
}
return data;
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_updatewlan_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_80211_updatewlan_element_create,
.parse = capwap_80211_updatewlan_element_parsing,
.clone = capwap_80211_updatewlan_element_clone,
.free = capwap_80211_updatewlan_element_free
};

View File

@ -0,0 +1,42 @@
#ifndef __CAPWAP_ELEMENT_80211_UPDATE_WLAN_HEADER__
#define __CAPWAP_ELEMENT_80211_UPDATE_WLAN_HEADER__
#define CAPWAP_ELEMENT_80211_UPDATE_WLAN_VENDOR 0
#define CAPWAP_ELEMENT_80211_UPDATE_WLAN_TYPE 1044
#define CAPWAP_ELEMENT_80211_UPDATE_WLAN (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_UPDATE_WLAN_VENDOR, .type = CAPWAP_ELEMENT_80211_UPDATE_WLAN_TYPE }
#define CAPWAP_UPDATE_WLAN_CAPABILITY_ESS 0x8000
#define CAPWAP_UPDATE_WLAN_CAPABILITY_IBSS 0x4000
#define CAPWAP_UPDATE_WLAN_CAPABILITY_CFPOLLABLE 0x2000
#define CAPWAP_UPDATE_WLAN_CAPABILITY_CFPOLLREQUEST 0x1000
#define CAPWAP_UPDATE_WLAN_CAPABILITY_PRIVACY 0x0800
#define CAPWAP_UPDATE_WLAN_CAPABILITY_SHORTPREAMBLE 0x0400
#define CAPWAP_UPDATE_WLAN_CAPABILITY_PBCC 0x0200
#define CAPWAP_UPDATE_WLAN_CAPABILITY_CHANNELAGILITY 0x0100
#define CAPWAP_UPDATE_WLAN_CAPABILITY_SPECTRUMMAN 0x0080
#define CAPWAP_UPDATE_WLAN_CAPABILITY_QOS 0x0040
#define CAPWAP_UPDATE_WLAN_CAPABILITY_SHORTSLOTTIME 0x0020
#define CAPWAP_UPDATE_WLAN_CAPABILITY_APSD 0x0010
#define CAPWAP_UPDATE_WLAN_CAPABILITY_DSSS_OFDM 0x0004
#define CAPWAP_UPDATE_WLAN_CAPABILITY_DELAYEDACK 0x0002
#define CAPWAP_UPDATE_WLAN_CAPABILITY_IMMEDIATEACK 0x0001
#define CAPWAP_UPDATE_WLAN_KEY_STATUS_MULTICASTKEY 0
#define CAPWAP_UPDATE_WLAN_KEY_STATUS_WEP 1
#define CAPWAP_UPDATE_WLAN_KEY_STATUS_REKEYINGGTK 2
#define CAPWAP_UPDATE_WLAN_KEY_STATUS_COMPLETEGTK 3
struct capwap_80211_updatewlan_element {
uint8_t radioid;
uint8_t wlanid;
uint16_t capability;
uint8_t keyindex;
uint8_t keystatus;
uint16_t keylength;
uint8_t* key;
};
extern const struct capwap_message_elements_ops capwap_element_80211_updatewlan_ops;
#endif /* __CAPWAP_ELEMENT_80211_UPDATE_WLAN_HEADER__ */

100
lib/element_80211_wtpqos.c Normal file
View File

@ -0,0 +1,100 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID |Tagging Policy | QoS Sub-Element ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Queue Depth | CWMin | CWMax |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| CWMax | AIFS | Reserved|8021p|RSV| DSCP Tag |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1045 for IEEE 802.11 WTP Quality of Service
Length: 34
********************************************************************/
/* */
static void capwap_80211_wtpqos_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
int i;
struct capwap_80211_wtpqos_element* element = (struct capwap_80211_wtpqos_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->taggingpolicy);
for (i = 0; i < CAPWAP_UPDATE_STATION_QOS_SUBELEMENTS; i++) {
func->write_u8(handle, element->qos[i].queuedepth);
func->write_u16(handle, element->qos[i].cwmin);
func->write_u16(handle, element->qos[i].cwmax);
func->write_u8(handle, element->qos[i].aifs);
func->write_u8(handle, element->qos[i].priority8021p & CAPWAP_WTP_QOS_PRIORIY_MASK);
func->write_u8(handle, element->qos[i].dscp & CAPWAP_WTP_QOS_DSCP_MASK);
}
}
/* */
static void* capwap_80211_wtpqos_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
int i;
struct capwap_80211_wtpqos_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 34) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 WTP QoS element");
return NULL;
}
/* */
data = (struct capwap_80211_wtpqos_element*)capwap_alloc(sizeof(struct capwap_80211_wtpqos_element));
memset(data, 0, sizeof(struct capwap_80211_wtpqos_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->taggingpolicy);
for (i = 0; i < CAPWAP_UPDATE_STATION_QOS_SUBELEMENTS; i++) {
func->read_u8(handle, &data->qos[i].queuedepth);
func->read_u16(handle, &data->qos[i].cwmin);
func->read_u16(handle, &data->qos[i].cwmax);
func->read_u8(handle, &data->qos[i].aifs);
func->read_u8(handle, &data->qos[i].priority8021p);
data->qos[i].priority8021p &= CAPWAP_UPDATE_STATION_QOS_PRIORIY_MASK;
func->read_u8(handle, &data->qos[i].dscp);
data->qos[i].dscp &= CAPWAP_UPDATE_STATION_QOS_DSCP_MASK;
}
return data;
}
/* */
static void* capwap_80211_wtpqos_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_wtpqos_element));
}
/* */
static void capwap_80211_wtpqos_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_wtpqos_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211_wtpqos_element_create,
.parse = capwap_80211_wtpqos_element_parsing,
.clone = capwap_80211_wtpqos_element_clone,
.free = capwap_80211_wtpqos_element_free
};

View File

@ -0,0 +1,37 @@
#ifndef __CAPWAP_ELEMENT_80211_WTP_QOS_HEADER__
#define __CAPWAP_ELEMENT_80211_WTP_QOS_HEADER__
#define CAPWAP_ELEMENT_80211_WTP_QOS_VENDOR 0
#define CAPWAP_ELEMENT_80211_WTP_QOS_TYPE 1045
#define CAPWAP_ELEMENT_80211_WTP_QOS (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_WTP_QOS_VENDOR, .type = CAPWAP_ELEMENT_80211_WTP_QOS_TYPE }
#define CAPWAP_WTP_QOS_SUBELEMENT_VOICE 0
#define CAPWAP_WTP_QOS_SUBELEMENT_VIDEO 1
#define CAPWAP_WTP_QOS_SUBELEMENT_BESTEFFORT 2
#define CAPWAP_WTP_QOS_SUBELEMENT_BACKGROUND 3
#define CAPWAP_WTP_QOS_SUBELEMENTS 4
#define CAPWAP_WTP_QOS_POLICY_MASK 0x1f
#define CAPWAP_WTP_QOS_PRIORIY_MASK 0x07
#define CAPWAP_WTP_QOS_DSCP_MASK 0x3f
struct capwap_80211_wtpqos_subelement {
uint8_t queuedepth;
uint16_t cwmin;
uint16_t cwmax;
uint8_t aifs;
uint8_t priority8021p;
uint8_t dscp;
};
struct capwap_80211_wtpqos_element {
uint8_t radioid;
uint8_t taggingpolicy;
struct capwap_80211_wtpqos_subelement qos[CAPWAP_WTP_QOS_SUBELEMENTS];
};
extern const struct capwap_message_elements_ops capwap_element_80211_wtpqos_ops;
#endif /* __CAPWAP_ELEMENT_80211_WTP_QOS_HEADER__ */

View File

@ -0,0 +1,88 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID |Short Preamble| Num of BSSIDs | DTIM Period |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BSSID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BSSID | Beacon Period |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Country String |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1046 for IEEE 802.11 WTP WLAN Radio Configuration
Length: 16
********************************************************************/
/* */
static void capwap_80211_wtpradioconf_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_wtpradioconf_element* element = (struct capwap_80211_wtpradioconf_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->shortpreamble);
func->write_u8(handle, element->maxbssid);
func->write_u8(handle, element->dtimperiod);
func->write_block(handle, element->bssid, MACADDRESS_EUI48_LENGTH);
func->write_u16(handle, element->beaconperiod);
func->write_block(handle, element->country, CAPWAP_WTP_RADIO_CONF_COUNTRY_LENGTH);
}
/* */
static void* capwap_80211_wtpradioconf_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_80211_wtpradioconf_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 16) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 WTP WLAN Radio Configuration element");
return NULL;
}
/* */
data = (struct capwap_80211_wtpradioconf_element*)capwap_alloc(sizeof(struct capwap_80211_wtpradioconf_element));
memset(data, 0, sizeof(struct capwap_80211_wtpradioconf_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->shortpreamble);
func->read_u8(handle, &data->maxbssid);
func->read_u8(handle, &data->dtimperiod);
func->read_block(handle, data->bssid, MACADDRESS_EUI48_LENGTH);
func->read_u16(handle, &data->beaconperiod);
func->read_block(handle, data->country, CAPWAP_WTP_RADIO_CONF_COUNTRY_LENGTH);
return data;
}
/* */
static void* capwap_80211_wtpradioconf_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_wtpradioconf_element));
}
/* */
static void capwap_80211_wtpradioconf_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_wtpradioconf_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211_wtpradioconf_element_create,
.parse = capwap_80211_wtpradioconf_element_parsing,
.clone = capwap_80211_wtpradioconf_element_clone,
.free = capwap_80211_wtpradioconf_element_free
};

View File

@ -0,0 +1,26 @@
#ifndef __CAPWAP_ELEMENT_80211_WTP_RADIO_CONF_HEADER__
#define __CAPWAP_ELEMENT_80211_WTP_RADIO_CONF_HEADER__
#define CAPWAP_ELEMENT_80211_WTP_RADIO_CONF_VENDOR 0
#define CAPWAP_ELEMENT_80211_WTP_RADIO_CONF_TYPE 1046
#define CAPWAP_ELEMENT_80211_WTP_RADIO_CONF (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_WTP_RADIO_CONF_VENDOR, .type = CAPWAP_ELEMENT_80211_WTP_RADIO_CONF_TYPE }
#define CAPWAP_WTP_RADIO_CONF_COUNTRY_LENGTH 4
#define CAPWAP_WTP_RADIO_CONF_SHORTPREAMBLE_DISABLE 0
#define CAPWAP_WTP_RADIO_CONF_SHORTPREAMBLE_ENABLE 1
struct capwap_80211_wtpradioconf_element {
uint8_t radioid;
uint8_t shortpreamble;
uint8_t maxbssid;
uint8_t dtimperiod;
uint8_t bssid[MACADDRESS_EUI48_LENGTH];
uint16_t beaconperiod;
uint8_t country[CAPWAP_WTP_RADIO_CONF_COUNTRY_LENGTH];
};
extern const struct capwap_message_elements_ops capwap_element_80211_wtpradioconf_ops;
#endif /* __CAPWAP_ELEMENT_80211_WTP_RADIO_CONF_HEADER__ */

View File

@ -0,0 +1,76 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Type | Status | Pad |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1047 for IEEE 802.11 WTP Radio Fail Alarm Indication
Length: 4
********************************************************************/
/* */
static void capwap_80211_wtpradiofailalarm_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_wtpradiofailalarm_element* element = (struct capwap_80211_wtpradiofailalarm_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->type);
func->write_u8(handle, element->status);
func->write_u8(handle, element->pad);
}
/* */
static void* capwap_80211_wtpradiofailalarm_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_80211_wtpradiofailalarm_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 4) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 WTP Radio Fail Alarm Indication element");
return NULL;
}
/* */
data = (struct capwap_80211_wtpradiofailalarm_element*)capwap_alloc(sizeof(struct capwap_80211_wtpradiofailalarm_element));
memset(data, 0, sizeof(struct capwap_80211_wtpradiofailalarm_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->type);
func->read_u8(handle, &data->status);
func->read_u8(handle, &data->pad);
return data;
}
/* */
static void* capwap_80211_wtpradiofailalarm_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_wtpradiofailalarm_element));
}
/* */
static void capwap_80211_wtpradiofailalarm_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_wtpradiofailalarm_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_80211_wtpradiofailalarm_element_create,
.parse = capwap_80211_wtpradiofailalarm_element_parsing,
.clone = capwap_80211_wtpradiofailalarm_element_clone,
.free = capwap_80211_wtpradiofailalarm_element_free
};

View File

@ -0,0 +1,21 @@
#ifndef __CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM_HEADER__
#define __CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM_HEADER__
#define CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM_VENDOR 0
#define CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM_TYPE 1047
#define CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM_VENDOR, .type = CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM_TYPE }
#define CAPWAP_WTP_RADIO_FAIL_ALARM_TYPE_RECEIVER 1
#define CAPWAP_WTP_RADIO_FAIL_ALARM_TYPE_TRANSMITTER 2
struct capwap_80211_wtpradiofailalarm_element {
uint8_t radioid;
uint8_t type;
uint8_t status;
uint8_t pad;
};
extern const struct capwap_message_elements_ops capwap_element_80211_wtpradiofailalarm_ops;
#endif /* __CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM_HEADER__ */

View File

@ -0,0 +1,75 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Radio Type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio Type |
+-+-+-+-+-+-+-+-+
Type: 1048 for IEEE 802.11 WTP Radio Information
Length: 5
********************************************************************/
/* */
static void capwap_80211_wtpradioinformation_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_80211_wtpradioinformation_element* element = (struct capwap_80211_wtpradioinformation_element*)data;
ASSERT(data != NULL);
/* */
func->write_u8(handle, element->radioid);
func->write_u32(handle, element->radiotype);
}
/* */
static void* capwap_80211_wtpradioinformation_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_80211_wtpradioinformation_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 5) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11 WTP Radio Information element");
return NULL;
}
/* */
data = (struct capwap_80211_wtpradioinformation_element*)capwap_alloc(sizeof(struct capwap_80211_wtpradioinformation_element));
memset(data, 0, sizeof(struct capwap_80211_wtpradioinformation_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u32(handle, &data->radiotype);
return data;
}
/* */
static void* capwap_80211_wtpradioinformation_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211_wtpradioinformation_element));
}
/* */
static void capwap_80211_wtpradioinformation_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211_wtpradioinformation_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211_wtpradioinformation_element_create,
.parse = capwap_80211_wtpradioinformation_element_parsing,
.clone = capwap_80211_wtpradioinformation_element_clone,
.free = capwap_80211_wtpradioinformation_element_free
};

View File

@ -0,0 +1,22 @@
#ifndef __CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_HEADER__
#define __CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_HEADER__
#define CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_VENDOR 0
#define CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_TYPE 1048
#define CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_VENDOR, .type = CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_TYPE }
#define CAPWAP_RADIO_TYPE_80211B 0x00000001
#define CAPWAP_RADIO_TYPE_80211A 0x00000002
#define CAPWAP_RADIO_TYPE_80211G 0x00000004
#define CAPWAP_RADIO_TYPE_80211N 0x00000008
#define CAPWAP_RADIO_TYPE_MASK 0x0000000f
struct capwap_80211_wtpradioinformation_element {
uint8_t radioid;
uint32_t radiotype;
};
extern const struct capwap_message_elements_ops capwap_element_80211_wtpradioinformation_ops;
#endif /* __CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_HEADER__ */

View File

@ -0,0 +1,93 @@
#include "capwap.h"
#include "element.h"
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Radio ID |S|P|N|G|B| | MaxSup MCS | Max MandMCS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TxAntenna | RxAntenna | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Type: TBD1 for IEEE 802.11n WLAN Radio Configuration
*
*/
/* */
static void
capwap_80211n_radioconf_element_create(void *data,
capwap_message_elements_handle handle,
struct capwap_write_message_elements_ops *func)
{
struct capwap_80211n_radioconf_element *element = (struct capwap_80211n_radioconf_element *)data;
ASSERT(data != NULL);
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->flags & CAPWAP_80211N_RADIO_CONF_MASK);
func->write_u8(handle, element->maxsupmcs);
func->write_u8(handle, element->maxmandmcs);
func->write_u8(handle, element->txant);
func->write_u8(handle, element->rxant);
func->write_u16(handle, 0);
}
/* */
static void *
capwap_80211n_radioconf_element_parsing(capwap_message_elements_handle handle,
struct capwap_read_message_elements_ops *func)
{
struct capwap_80211n_radioconf_element *data;
uint16_t reserved;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 8) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11n Radio Configuration element");
return NULL;
}
/* */
data = (struct capwap_80211n_radioconf_element*)capwap_alloc(sizeof(struct capwap_80211n_radioconf_element));
memset(data, 0, sizeof(struct capwap_80211n_radioconf_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->flags);
func->read_u8(handle, &data->maxsupmcs);
func->read_u8(handle, &data->maxmandmcs);
func->read_u8(handle, &data->txant);
func->read_u8(handle, &data->rxant);
func->read_u16(handle, &reserved);
return data;
}
/* */
static void *
capwap_80211n_radioconf_element_clone(void *data)
{
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211n_radioconf_element));
}
/* */
static void
capwap_80211n_radioconf_element_free(void* data)
{
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211n_radioconf_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_80211n_radioconf_element_create,
.parse = capwap_80211n_radioconf_element_parsing,
.clone = capwap_80211n_radioconf_element_clone,
.free = capwap_80211n_radioconf_element_free
};

View File

@ -0,0 +1,28 @@
#ifndef __CAPWAP_ELEMENT_80211N_RADIO_CONF_HEADER__
#define __CAPWAP_ELEMENT_80211N_RADIO_CONF_HEADER__
#define CAPWAP_ELEMENT_80211N_RADIO_CONF_VENDOR CAPWAP_VENDOR_TRAVELPING_ID
#define CAPWAP_ELEMENT_80211N_RADIO_CONF_TYPE 16
#define CAPWAP_ELEMENT_80211N_RADIO_CONF (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211N_RADIO_CONF_VENDOR, .type = CAPWAP_ELEMENT_80211N_RADIO_CONF_TYPE }
#define CAPWAP_80211N_RADIO_CONF_A_MSDU (1 << 7)
#define CAPWAP_80211N_RADIO_CONF_A_MPDU (1 << 6)
#define CAPWAP_80211N_RADIO_CONF_11N_ONLY (1 << 5)
#define CAPWAP_80211N_RADIO_CONF_SHORT_GUARD_INTERVAL (1 << 4)
#define CAPWAP_80211N_RADIO_CONF_20MHZ_BANDWITH (1 << 3)
#define CAPWAP_80211N_RADIO_CONF_MASK 0xF8
struct capwap_80211n_radioconf_element {
uint8_t radioid;
uint8_t flags;
uint8_t maxsupmcs;
uint8_t maxmandmcs;
uint8_t txant;
uint8_t rxant;
};
extern const struct capwap_message_elements_ops capwap_element_80211n_radioconf_ops;
#endif /* __CAPWAP_ELEMENT_80211N_RADIO_CONF_HEADER__ */

View File

@ -0,0 +1,102 @@
#include "capwap.h"
#include "element.h"
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | MAC Address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | MAC Address |S| P |T|F|H|M| | Max RxFactor |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Min StaSpacing| HiSuppDataRate | AMPDUBufSize |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | AMPDUBufSize | HtcSupp | MCS Set |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | MCS Set |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | MCS Set |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Type: TBD2 for IEEE 802.11n Station Information
*
*/
/* */
static void
capwap_80211n_station_info_element_create(void *data,
capwap_message_elements_handle handle,
struct capwap_write_message_elements_ops *func)
{
struct capwap_80211n_station_info_element *element = (struct capwap_80211n_station_info_element *)data;
ASSERT(data != NULL);
func->write_block(handle, element->address, MACADDRESS_EUI48_LENGTH);
func->write_u8(handle, element->flags);
func->write_u8(handle, element->maxrxfactor);
func->write_u8(handle, element->minstaspaceing);
func->write_u16(handle, element->hisuppdatarate);
func->write_u16(handle, element->ampdubufsize);
func->write_u8(handle, element->htcsupp);
func->write_block(handle, element->mcsset, MCS_SET_LENGTH);
}
/* */
static void *
capwap_80211n_station_info_element_parsing(capwap_message_elements_handle handle,
struct capwap_read_message_elements_ops *func)
{
struct capwap_80211n_station_info_element *data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 24) {
log_printf(LOG_DEBUG, "Invalid IEEE 802.11n Station Information");
return NULL;
}
/* */
data = (struct capwap_80211n_station_info_element*)capwap_alloc(sizeof(struct capwap_80211n_station_info_element));
memset(data, 0, sizeof(struct capwap_80211n_station_info_element));
/* Retrieve data */
func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH);
func->read_u8(handle, &data->flags);
func->read_u8(handle, &data->maxrxfactor);
func->read_u8(handle, &data->minstaspaceing);
func->read_u16(handle, &data->hisuppdatarate);
func->read_u16(handle, &data->ampdubufsize);
func->read_u8(handle, &data->htcsupp);
func->read_block(handle, data->mcsset, MCS_SET_LENGTH);
return data;
}
/* */
static void *
capwap_80211n_station_info_element_clone(void *data)
{
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_80211n_station_info_element));
}
/* */
static void
capwap_80211n_station_info_element_free(void* data)
{
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_80211n_station_info_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_80211n_station_info_element_create,
.parse = capwap_80211n_station_info_element_parsing,
.clone = capwap_80211n_station_info_element_clone,
.free = capwap_80211n_station_info_element_free
};

View File

@ -0,0 +1,32 @@
#ifndef __CAPWAP_ELEMENT_80211N_STATION_INFO_HEADER__
#define __CAPWAP_ELEMENT_80211N_STATION_INFO_HEADER__
#define CAPWAP_ELEMENT_80211N_STATION_INFO_VENDOR CAPWAP_VENDOR_TRAVELPING_ID
#define CAPWAP_ELEMENT_80211N_STATION_INFO_TYPE 17
#define CAPWAP_ELEMENT_80211N_STATION_INFO (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211N_STATION_INFO_VENDOR, .type = CAPWAP_ELEMENT_80211N_STATION_INFO_TYPE }
#define CAPWAP_80211N_STATION_INFO_40MHZ_BANDWITH (1 << 7)
#define CAPWAP_80211N_STATION_INFO_POWER_SAVE_MODE ((1 << 6) | (1 << 5))
#define CAPWAP_80211N_STATION_INFO_POWER_SAVE_MODE_SHIFT 5
#define CAPWAP_80211N_STATION_INFO_SHORT_GUARD_INTERVAL_AT_20MHZ (1 << 4)
#define CAPWAP_80211N_STATION_INFO_SHORT_GUARD_INTERVAL_AT_40MHZ (1 << 3)
#define CAPWAP_80211N_STATION_INFO_BLOCK_ACK_DELAY_MODE (1 << 2)
#define CAPWAP_80211N_STATION_INFO_MAX_AMSDU_LENGTH_7935 (1 << 1)
#define MCS_SET_LENGTH 10
struct capwap_80211n_station_info_element {
uint8_t address[MACADDRESS_EUI48_LENGTH];
uint8_t flags;
uint8_t maxrxfactor;
uint8_t minstaspaceing;
uint16_t hisuppdatarate;
uint16_t ampdubufsize;
uint8_t htcsupp;
uint8_t mcsset[MCS_SET_LENGTH];
};
extern const struct capwap_message_elements_ops capwap_element_80211n_station_info_ops;
#endif /* __CAPWAP_ELEMENT_80211N_STATION_INFO_HEADER__ */

207
lib/element_acdescriptor.c Normal file
View File

@ -0,0 +1,207 @@
#include "capwap.h"
#include "array.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Stations | Limit |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Active WTPs | Max WTPs |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Security | R-MAC Field | Reserved1 | DTLS Policy |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| AC Information Sub-Element...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| AC Information Vendor Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| AC Information Type | AC Information Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| AC Information Data...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 1 for AC Descriptor
Length: >= 12
********************************************************************/
/* */
static void capwap_acdescriptor_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
int i;
struct capwap_acdescriptor_element* element = (struct capwap_acdescriptor_element*)data;
ASSERT(data != NULL);
ASSERT(!(element->security & ~CAPWAP_ACDESC_SECURITY_MASK));
ASSERT(!(element->dtlspolicy & ~CAPWAP_ACDESC_DTLS_POLICY_MASK));
ASSERT((element->rmacfield == CAPWAP_ACDESC_RMACFIELD_SUPPORTED) || (element->rmacfield == CAPWAP_ACDESC_RMACFIELD_NOTSUPPORTED));
ASSERT(element->descsubelement != NULL);
/* */
func->write_u16(handle, element->stations);
func->write_u16(handle, element->stationlimit);
func->write_u16(handle, element->activewtp);
func->write_u16(handle, element->maxwtp);
func->write_u8(handle, element->security);
func->write_u8(handle, element->rmacfield);
func->write_u8(handle, 0);
func->write_u8(handle, element->dtlspolicy);
/* */
for (i = 0; i < element->descsubelement->count; i++) {
struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(element->descsubelement, i);
ASSERT(desc->length > 0);
ASSERT(desc->data != NULL);
func->write_u32(handle, desc->vendor);
func->write_u16(handle, desc->type);
func->write_u16(handle, desc->length);
func->write_block(handle, desc->data, desc->length);
}
}
/* */
static void* capwap_acdescriptor_element_clone(void* data) {
int i;
struct capwap_acdescriptor_element* cloneelement;
struct capwap_acdescriptor_element* element = (struct capwap_acdescriptor_element*)data;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_acdescriptor_element));
cloneelement->descsubelement = capwap_array_create(sizeof(struct capwap_acdescriptor_desc_subelement), 0, 1);
for (i = 0; i < element->descsubelement->count; i++) {
struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(element->descsubelement, i);
struct capwap_acdescriptor_desc_subelement* clonedesc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(cloneelement->descsubelement, i);
memcpy(clonedesc, desc, sizeof(struct capwap_acdescriptor_desc_subelement));
if (desc->length) {
clonedesc->data = capwap_clone(desc->data, desc->length);
}
}
return cloneelement;
}
/* */
static void capwap_acdescriptor_element_free(void* data) {
int i;
struct capwap_acdescriptor_element* element = (struct capwap_acdescriptor_element*)data;
ASSERT(element != NULL);
ASSERT(element->descsubelement != NULL);
/* */
for (i = 0; i < element->descsubelement->count; i++) {
struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(element->descsubelement, i);
if (desc->data) {
capwap_free(desc->data);
}
}
capwap_array_free(element->descsubelement);
capwap_free(data);
}
/* */
static void* capwap_acdescriptor_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_acdescriptor_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) < 12) {
log_printf(LOG_DEBUG, "Invalid AC Descriptor element: underbuffer");
return NULL;
}
/* */
data = (struct capwap_acdescriptor_element*)capwap_alloc(sizeof(struct capwap_acdescriptor_element));
memset(data, 0, sizeof(struct capwap_acdescriptor_element));
data->descsubelement = capwap_array_create(sizeof(struct capwap_acdescriptor_desc_subelement), 0, 1);
/* Retrieve data */
func->read_u16(handle, &data->stations);
func->read_u16(handle, &data->stationlimit);
func->read_u16(handle, &data->activewtp);
func->read_u16(handle, &data->maxwtp);
/* Check */
if (data->stations > data->stationlimit) {
log_printf(LOG_DEBUG, "Invalid AC Descriptor element: stations > stationlimit");
capwap_acdescriptor_element_free(data);
return NULL;
} else if (data->activewtp > data->maxwtp) {
log_printf(LOG_DEBUG, "Invalid AC Descriptor element: activewtp > maxwtp");
capwap_acdescriptor_element_free(data);
return NULL;
}
/* */
func->read_u8(handle, &data->security);
func->read_u8(handle, &data->rmacfield);
func->read_u8(handle, NULL);
func->read_u8(handle, &data->dtlspolicy);
/* */
if (data->security & ~CAPWAP_ACDESC_SECURITY_MASK) {
log_printf(LOG_DEBUG, "Invalid AC Descriptor element: security");
capwap_acdescriptor_element_free(data);
return NULL;
} else if (data->dtlspolicy & ~CAPWAP_ACDESC_DTLS_POLICY_MASK) {
log_printf(LOG_DEBUG, "Invalid AC Descriptor element: dtlspolicy");
capwap_acdescriptor_element_free(data);
return NULL;
} else if ((data->rmacfield != CAPWAP_ACDESC_RMACFIELD_SUPPORTED) && (data->rmacfield != CAPWAP_ACDESC_RMACFIELD_NOTSUPPORTED)) {
log_printf(LOG_DEBUG, "Invalid AC Descriptor element: rmacfield");
capwap_acdescriptor_element_free(data);
return NULL;
}
/* Description Subelement */
while (func->read_ready(handle) > 0) {
unsigned short length;
struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(data->descsubelement, data->descsubelement->count);
/* */
func->read_u32(handle, &desc->vendor);
func->read_u16(handle, &desc->type);
func->read_u16(handle, &desc->length);
if ((desc->type != CAPWAP_ACDESC_SUBELEMENT_HARDWAREVERSION) && (desc->type != CAPWAP_ACDESC_SUBELEMENT_SOFTWAREVERSION)) {
log_printf(LOG_DEBUG, "Invalid AC Descriptor subelement: type");
capwap_acdescriptor_element_free(data);
return NULL;
}
/* Check buffer size */
length = func->read_ready(handle);
if ((length > CAPWAP_ACDESC_SUBELEMENT_MAXDATA) || (length < desc->length)) {
log_printf(LOG_DEBUG, "Invalid AC Descriptor subelement: length");
capwap_acdescriptor_element_free(data);
return NULL;
}
desc->data = (uint8_t*)capwap_alloc(desc->length + 1);
func->read_block(handle, desc->data, desc->length);
desc->data[desc->length] = 0;
}
return data;
}
/* */
const struct capwap_message_elements_ops capwap_element_acdescriptor_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_acdescriptor_element_create,
.parse = capwap_acdescriptor_element_parsing,
.clone = capwap_acdescriptor_element_clone,
.free = capwap_acdescriptor_element_free
};

View File

@ -0,0 +1,44 @@
#ifndef __CAPWAP_ELEMENT_ACDESCRIPTOR_HEADER__
#define __CAPWAP_ELEMENT_ACDESCRIPTOR_HEADER__
#define CAPWAP_ELEMENT_ACDESCRIPTION_VENDOR 0
#define CAPWAP_ELEMENT_ACDESCRIPTION_TYPE 1
#define CAPWAP_ELEMENT_ACDESCRIPTION (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_ACDESCRIPTION_VENDOR, .type = CAPWAP_ELEMENT_ACDESCRIPTION_TYPE }
#define CAPWAP_ACDESC_SECURITY_PRESHARED_KEY 0x04
#define CAPWAP_ACDESC_SECURITY_X509_CERT 0x02
#define CAPWAP_ACDESC_SECURITY_MASK 0x06
#define CAPWAP_ACDESC_RMACFIELD_SUPPORTED 1
#define CAPWAP_ACDESC_RMACFIELD_NOTSUPPORTED 2
#define CAPWAP_ACDESC_DTLS_DATA_CHANNEL_ENABLED 0x04
#define CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED 0x02
#define CAPWAP_ACDESC_DTLS_POLICY_MASK 0x06
struct capwap_acdescriptor_element {
uint16_t stations;
uint16_t stationlimit;
uint16_t activewtp;
uint16_t maxwtp;
uint8_t security;
uint8_t rmacfield;
uint8_t dtlspolicy;
struct capwap_array* descsubelement;
};
#define CAPWAP_ACDESC_SUBELEMENT_HARDWAREVERSION 4
#define CAPWAP_ACDESC_SUBELEMENT_SOFTWAREVERSION 5
#define CAPWAP_ACDESC_SUBELEMENT_MAXDATA 1024
struct capwap_acdescriptor_desc_subelement {
uint32_t vendor;
uint16_t type;
uint16_t length;
uint8_t* data;
};
extern const struct capwap_message_elements_ops capwap_element_acdescriptor_ops;
#endif /* __CAPWAP_ELEMENT_ACDESCRIPTOR_HEADER__ */

91
lib/element_acipv4list.c Normal file
View File

@ -0,0 +1,91 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IP Address[] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 2 for AC IPv4 List
Length: >= 4
********************************************************************/
/* */
static void capwap_acipv4list_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
unsigned long i;
struct capwap_acipv4list_element* element = (struct capwap_acipv4list_element*)data;
ASSERT(data != NULL);
/* */
for (i = 0; i < element->addresses->count; i++) {
func->write_block(handle, (uint8_t*)capwap_array_get_item_pointer(element->addresses, i), sizeof(struct in_addr));
}
}
/* */
static void* capwap_acipv4list_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
uint16_t length;
struct capwap_acipv4list_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if ((length >= 4) && (length <= CAPWAP_ACIPV4LIST_MAX_ELEMENTS * 4) && (length % 4)) {
log_printf(LOG_DEBUG, "Invalid AC IPv4 List element: unbuffer");
return NULL;
}
/* Retrieve data */
data = (struct capwap_acipv4list_element*)capwap_alloc(sizeof(struct capwap_acipv4list_element));
data->addresses = capwap_array_create(sizeof(struct in_addr), 0, 0);
while (length > 0) {
struct in_addr* address = (struct in_addr*)capwap_array_get_item_pointer(data->addresses, data->addresses->count);
func->read_block(handle, (uint8_t*)address, sizeof(struct in_addr));
length -= 4;
}
return data;
}
/* */
static void* capwap_acipv4list_element_clone(void* data) {
int i;
struct capwap_acipv4list_element* cloneelement;
struct capwap_acipv4list_element* element = (struct capwap_acipv4list_element*)data;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_acipv4list_element));
cloneelement->addresses = capwap_array_create(sizeof(struct in_addr), 0, 0);
for (i = 0; i < element->addresses->count; i++) {
memcpy(capwap_array_get_item_pointer(cloneelement->addresses, i), capwap_array_get_item_pointer(element->addresses, i), sizeof(struct in_addr));
}
return cloneelement;
}
/* */
static void capwap_acipv4list_element_free(void* data) {
struct capwap_acipv4list_element* element = (struct capwap_acipv4list_element*)data;
ASSERT(data != NULL);
capwap_array_free(element->addresses);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_acipv4list_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_acipv4list_element_create,
.parse = capwap_acipv4list_element_parsing,
.clone = capwap_acipv4list_element_clone,
.free = capwap_acipv4list_element_free
};

17
lib/element_acipv4list.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef __CAPWAP_ELEMENT_ACIPV4LIST_HEADER__
#define __CAPWAP_ELEMENT_ACIPV4LIST_HEADER__
#define CAPWAP_ELEMENT_ACIPV4LIST_VENDOR 0
#define CAPWAP_ELEMENT_ACIPV4LIST_TYPE 2
#define CAPWAP_ELEMENT_ACIPV4LIST (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_ACIPV4LIST_VENDOR, .type = CAPWAP_ELEMENT_ACIPV4LIST_TYPE }
#define CAPWAP_ACIPV4LIST_MAX_ELEMENTS 1024
struct capwap_acipv4list_element {
struct capwap_array* addresses;
};
extern const struct capwap_message_elements_ops capwap_element_acipv4list_ops;
#endif /* __CAPWAP_ELEMENT_ACIPV4LIST_HEADER__ */

97
lib/element_acipv6list.c Normal file
View File

@ -0,0 +1,97 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 3 for AC IPV6 List
Length: >= 16
********************************************************************/
/* */
static void capwap_acipv6list_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
unsigned long i;
struct capwap_acipv6list_element* element = (struct capwap_acipv6list_element*)data;
ASSERT(data != NULL);
/* */
for (i = 0; i < element->addresses->count; i++) {
func->write_block(handle, (uint8_t*)capwap_array_get_item_pointer(element->addresses, i), sizeof(struct in6_addr));
}
}
/* */
static void* capwap_acipv6list_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
uint16_t length;
struct capwap_acipv6list_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if ((length >= 16) && (length <= CAPWAP_ACIPV4LIST_MAX_ELEMENTS * 16) && (length % 16)) {
log_printf(LOG_DEBUG, "Invalid AC IPv6 List element: underbuffer");
return NULL;
}
/* Retrieve data */
data = (struct capwap_acipv6list_element*)capwap_alloc(sizeof(struct capwap_acipv6list_element));
data->addresses = capwap_array_create(sizeof(struct in6_addr), 0, 0);
while (length > 0) {
struct in6_addr* address = (struct in6_addr*)capwap_array_get_item_pointer(data->addresses, data->addresses->count);
func->read_block(handle, (uint8_t*)address, sizeof(struct in6_addr));
length -= 16;
}
return data;
}
/* */
static void* capwap_acipv6list_element_clone(void* data) {
int i;
struct capwap_acipv6list_element* cloneelement;
struct capwap_acipv6list_element* element = (struct capwap_acipv6list_element*)data;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_acipv6list_element));
cloneelement->addresses = capwap_array_create(sizeof(struct in6_addr), 0, 0);
for (i = 0; i < element->addresses->count; i++) {
memcpy(capwap_array_get_item_pointer(cloneelement->addresses, i), capwap_array_get_item_pointer(element->addresses, i), sizeof(struct in6_addr));
}
return cloneelement;
}
/* */
static void capwap_acipv6list_element_free(void* data) {
struct capwap_acipv6list_element* element = (struct capwap_acipv6list_element*)data;
ASSERT(data != NULL);
capwap_array_free(element->addresses);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_acipv6list_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_acipv6list_element_create,
.parse = capwap_acipv6list_element_parsing,
.clone = capwap_acipv6list_element_clone,
.free = capwap_acipv6list_element_free
};

17
lib/element_acipv6list.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef __CAPWAP_ELEMENT_ACIPV6LIST_HEADER__
#define __CAPWAP_ELEMENT_ACIPV6LIST_HEADER__
#define CAPWAP_ELEMENT_ACIPV6LIST_VENDOR 0
#define CAPWAP_ELEMENT_ACIPV6LIST_TYPE 3
#define CAPWAP_ELEMENT_ACIPV6LIST (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_ACIPV6LIST_VENDOR, .type = CAPWAP_ELEMENT_ACIPV6LIST_TYPE }
#define CAPWAP_ACIPV6LIST_MAX_ELEMENTS 1024
struct capwap_acipv6list_element {
struct capwap_array* addresses;
};
extern const struct capwap_message_elements_ops capwap_element_acipv6list_ops;
#endif /* __CAPWAP_ELEMENT_ACIPV6LIST_HEADER__ */

85
lib/element_acname.c Normal file
View File

@ -0,0 +1,85 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
| Name ...
+-+-+-+-+-+-+-+-+
Type: 4 for AC Name
Length: >= 1
********************************************************************/
/* */
static void capwap_acname_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_acname_element* element = (struct capwap_acname_element*)data;
ASSERT(data != NULL);
ASSERT(element->name != NULL);
func->write_block(handle, element->name, strlen((char*)element->name));
}
/* */
static void* capwap_acname_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
unsigned short length;
struct capwap_acname_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if ((length < 1) || (length > CAPWAP_ACNAME_MAXLENGTH)) {
log_printf(LOG_DEBUG, "Invalid AC Name element: underbuffer");
return NULL;
}
/* Retrieve data */
data = (struct capwap_acname_element*)capwap_alloc(sizeof(struct capwap_acname_element));
data->name = (uint8_t*)capwap_alloc(length + 1);
func->read_block(handle, data->name, length);
data->name[length] = 0;
return data;
}
/* */
static void* capwap_acname_element_clone(void* data) {
struct capwap_acname_element* cloneelement;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_acname_element));
if (cloneelement->name) {
cloneelement->name = (uint8_t*)capwap_duplicate_string((char*)((struct capwap_acname_element*)data)->name);
}
return cloneelement;
}
/* */
static void capwap_acname_element_free(void* data) {
struct capwap_acname_element* element = (struct capwap_acname_element*)data;
ASSERT(data != NULL);
if (element->name) {
capwap_free(element->name);
}
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_acname_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_acname_element_create,
.parse = capwap_acname_element_parsing,
.clone = capwap_acname_element_clone,
.free = capwap_acname_element_free
};

17
lib/element_acname.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef __CAPWAP_ELEMENT_ACNAME_HEADER__
#define __CAPWAP_ELEMENT_ACNAME_HEADER__
#define CAPWAP_ELEMENT_ACNAME_VENDOR 0
#define CAPWAP_ELEMENT_ACNAME_TYPE 4
#define CAPWAP_ELEMENT_ACNAME (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_ACNAME_VENDOR, .type = CAPWAP_ELEMENT_ACNAME_TYPE }
#define CAPWAP_ACNAME_MAXLENGTH 512
struct capwap_acname_element {
uint8_t* name;
};
extern const struct capwap_message_elements_ops capwap_element_acname_ops;
#endif /* __CAPWAP_ELEMENT_ACNAME_HEADER__ */

View File

@ -0,0 +1,86 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Priority | AC Name...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 5 for AC Name with Priority
Length: >= 2
********************************************************************/
/* */
static void capwap_acnamepriority_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_acnamepriority_element* element = (struct capwap_acnamepriority_element*)data;
ASSERT(data != NULL);
func->write_u8(handle, element->priority);
func->write_block(handle, element->name, strlen((char*)element->name));
}
/* */
static void* capwap_acnamepriority_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
unsigned short length;
struct capwap_acnamepriority_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle) - 1;
if ((length < 1) || (length > CAPWAP_ACNAMEPRIORITY_MAXLENGTH)) {
log_printf(LOG_DEBUG, "Invalid AC Name Priority element: underbuffer");
return NULL;
}
/* Retrieve data */
data = (struct capwap_acnamepriority_element*)capwap_alloc(sizeof(struct capwap_acnamepriority_element));
data->name = (uint8_t*)capwap_alloc(length + 1);
func->read_u8(handle, &data->priority);
func->read_block(handle, data->name, length);
data->name[length] = 0;
return data;
}
/* */
static void* capwap_acnamepriority_element_clone(void* data) {
struct capwap_acnamepriority_element* cloneelement;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_acnamepriority_element));
if (cloneelement->name) {
cloneelement->name = (uint8_t*)capwap_duplicate_string((char*)((struct capwap_acnamepriority_element*)data)->name);
}
return cloneelement;
}
/* */
static void capwap_acnamepriority_element_free(void* data) {
struct capwap_acnamepriority_element* element = (struct capwap_acnamepriority_element*)data;
ASSERT(data != NULL);
if (element->name) {
capwap_free(element->name);
}
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_acnamepriority_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_acnamepriority_element_create,
.parse = capwap_acnamepriority_element_parsing,
.clone = capwap_acnamepriority_element_clone,
.free = capwap_acnamepriority_element_free
};

View File

@ -0,0 +1,18 @@
#ifndef __CAPWAP_ELEMENT_ACNAMEPRIORITY_HEADER__
#define __CAPWAP_ELEMENT_ACNAMEPRIORITY_HEADER__
#define CAPWAP_ELEMENT_ACNAMEPRIORITY_VENDOR 0
#define CAPWAP_ELEMENT_ACNAMEPRIORITY_TYPE 5
#define CAPWAP_ELEMENT_ACNAMEPRIORITY (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_ACNAMEPRIORITY_VENDOR, .type = CAPWAP_ELEMENT_ACNAMEPRIORITY_TYPE }
#define CAPWAP_ACNAMEPRIORITY_MAXLENGTH 512
struct capwap_acnamepriority_element {
uint8_t priority;
uint8_t* name;
};
extern const struct capwap_message_elements_ops capwap_element_acnamepriority_ops;
#endif /* __CAPWAP_ELEMENT_ACNAMEPRIORITY_HEADER__ */

68
lib/element_actimestamp.c Normal file
View File

@ -0,0 +1,68 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 6 for AC Timestamp
Length: 4
********************************************************************/
/* */
static void capwap_actimestamp_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_actimestamp_element* element = (struct capwap_actimestamp_element*)data;
ASSERT(data != NULL);
/* */
func->write_u32(handle, element->timestamp);
}
/* */
static void* capwap_actimestamp_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_actimestamp_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 4) {
log_printf(LOG_DEBUG, "Invalid AC Timestamp element: underbuffer");
return NULL;
}
/* Retrieve data */
data = (struct capwap_actimestamp_element*)capwap_alloc(sizeof(struct capwap_actimestamp_element));
func->read_u32(handle, &data->timestamp);
return data;
}
/* */
static void* capwap_actimestamp_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_actimestamp_element));
}
/* */
static void capwap_actimestamp_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_actimestamp_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_actimestamp_element_create,
.parse = capwap_actimestamp_element_parsing,
.clone = capwap_actimestamp_element_clone,
.free = capwap_actimestamp_element_free
};

16
lib/element_actimestamp.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef __CAPWAP_ELEMENT_AC_TIMESTAMP_HEADER__
#define __CAPWAP_ELEMENT_AC_TIMESTAMP_HEADER__
#define CAPWAP_ELEMENT_ACTIMESTAMP_VENDOR 0
#define CAPWAP_ELEMENT_ACTIMESTAMP_TYPE 6
#define CAPWAP_ELEMENT_ACTIMESTAMP (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_ACTIMESTAMP_VENDOR, .type = CAPWAP_ELEMENT_ACTIMESTAMP_TYPE }
struct capwap_actimestamp_element {
uint32_t timestamp;
};
extern const struct capwap_message_elements_ops capwap_element_actimestamp_ops;
#endif /* __CAPWAP_ELEMENT_AC_TIMESTAMP_HEADER__ */

111
lib/element_addmacacl.c Normal file
View File

@ -0,0 +1,111 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Num of Entries| Length | MAC Address ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 7 for Add MAC ACL Entry
Length: >= 8
********************************************************************/
/* */
static void capwap_addmacacl_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_addmacacl_element* element = (struct capwap_addmacacl_element*)data;
ASSERT(data != NULL);
ASSERT(element->entry > 0);
ASSERT(IS_VALID_MACADDRESS_LENGTH(element->length));
func->write_u8(handle, element->entry);
func->write_u8(handle, element->length);
func->write_block(handle, element->address, element->entry * element->length);
}
/* */
static void* capwap_addmacacl_element_clone(void* data) {
struct capwap_addmacacl_element* cloneelement;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_addmacacl_element));
if (cloneelement->entry > 0) {
cloneelement->address = capwap_clone(((struct capwap_addmacacl_element*)data)->address, cloneelement->entry * cloneelement->length);
}
return cloneelement;
}
/* */
static void capwap_addmacacl_element_free(void* data) {
struct capwap_addmacacl_element* element = (struct capwap_addmacacl_element*)data;
ASSERT(data != NULL);
if (element->address) {
capwap_free(element->address);
}
capwap_free(data);
}
/* */
static void* capwap_addmacacl_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
unsigned short length;
struct capwap_addmacacl_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 8) {
log_printf(LOG_DEBUG, "Invalid Add MAC ACL Entry element: underbuffer");
return NULL;
}
length -= 2;
/* */
data = (struct capwap_addmacacl_element*)capwap_alloc(sizeof(struct capwap_addmacacl_element));
memset(data, 0, sizeof(struct capwap_addmacacl_element));
/* Retrieve data */
func->read_u8(handle, &data->entry);
func->read_u8(handle, &data->length);
if (!data->entry) {
capwap_addmacacl_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Add MAC ACL Entry element: invalid entry");
return NULL;
} else if (!IS_VALID_MACADDRESS_LENGTH(data->length)) {
capwap_addmacacl_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Add MAC ACL Entry element: invalid length");
return NULL;
}
if (length != (data->entry * data->length)) {
capwap_addmacacl_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Add MAC ACL Entry element: invalid total length");
return NULL;
}
data->address = (uint8_t*)capwap_alloc(length);
func->read_block(handle, data->address, length);
return data;
}
/* */
const struct capwap_message_elements_ops capwap_element_addmacacl_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_addmacacl_element_create,
.parse = capwap_addmacacl_element_parsing,
.clone = capwap_addmacacl_element_clone,
.free = capwap_addmacacl_element_free
};

17
lib/element_addmacacl.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef __CAPWAP_ELEMENT_ADD_MAC_ACL__HEADER__
#define __CAPWAP_ELEMENT_ADD_MAC_ACL__HEADER__
#define CAPWAP_ELEMENT_ADDMACACL_VENDOR 0
#define CAPWAP_ELEMENT_ADDMACACL_TYPE 7
#define CAPWAP_ELEMENT_ADDMACACL (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_ADDMACACL_VENDOR, .type = CAPWAP_ELEMENT_ADDMACACL_TYPE }
struct capwap_addmacacl_element {
uint8_t entry;
uint8_t length;
uint8_t* address;
};
extern const struct capwap_message_elements_ops capwap_element_addmacacl_ops;
#endif /* __CAPWAP_ELEMENT_ADD_MAC_ACL__HEADER__ */

135
lib/element_addstation.c Normal file
View File

@ -0,0 +1,135 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Length | MAC Address ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| VLAN Name...
+-+-+-+-+-+-+-+-+
Type: 8 for Add Station
Length: >= 8
********************************************************************/
/* */
static void capwap_addstation_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_addstation_element* element = (struct capwap_addstation_element*)data;
ASSERT(data != NULL);
ASSERT(IS_VALID_RADIOID(element->radioid));
ASSERT(IS_VALID_MACADDRESS_LENGTH(element->length));
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->length);
func->write_block(handle, element->address, element->length);
if (element->vlan && *element->vlan) {
unsigned short length = strlen((char*)element->vlan);
ASSERT(length <= CAPWAP_ADDSTATION_VLAN_MAX_LENGTH);
func->write_block(handle, element->vlan, length);
}
}
/* */
static void* capwap_addstation_element_clone(void* data) {
struct capwap_addstation_element* cloneelement;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_addstation_element));
if (cloneelement->length > 0) {
cloneelement->address = capwap_clone(((struct capwap_addstation_element*)data)->address, cloneelement->length);
}
if (cloneelement->vlan) {
cloneelement->vlan = (uint8_t*)capwap_duplicate_string((char*)((struct capwap_addstation_element*)data)->vlan);
}
return cloneelement;
}
/* */
static void capwap_addstation_element_free(void* data) {
struct capwap_addstation_element* element = (struct capwap_addstation_element*)data;
ASSERT(data != NULL);
if (element->vlan) {
capwap_free(element->vlan);
}
if (element->address) {
capwap_free(element->address);
}
capwap_free(element);
}
/* */
static void* capwap_addstation_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
unsigned short length;
struct capwap_addstation_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 8) {
log_printf(LOG_DEBUG, "Invalid Add Station element: underbuffer");
return NULL;
}
length -= 2;
/* */
data = (struct capwap_addstation_element*)capwap_alloc(sizeof(struct capwap_addstation_element));
memset(data, 0, sizeof(struct capwap_addstation_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->length);
if (!IS_VALID_RADIOID(data->radioid)) {
capwap_addstation_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Add Station element: invalid radio");
return NULL;
} else if (!IS_VALID_MACADDRESS_LENGTH(data->length) || (length < data->length)) {
capwap_addstation_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Add Station element: invalid length");
return NULL;
}
data->address = (uint8_t*)capwap_alloc(data->length);
func->read_block(handle, data->address, data->length);
length -= data->length;
if (length > 0) {
if (length <= CAPWAP_ADDSTATION_VLAN_MAX_LENGTH) {
data->vlan = (uint8_t*)capwap_alloc(length + 1);
func->read_block(handle, data->vlan, length);
data->vlan[length] = 0;
} else {
capwap_addstation_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Add Station element: invalid vlan");
return NULL;
}
}
return data;
}
/* */
const struct capwap_message_elements_ops capwap_element_addstation_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_addstation_element_create,
.parse = capwap_addstation_element_parsing,
.clone = capwap_addstation_element_clone,
.free = capwap_addstation_element_free
};

20
lib/element_addstation.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef __CAPWAP_ELEMENT_ADD_STATION__HEADER__
#define __CAPWAP_ELEMENT_ADD_STATION__HEADER__
#define CAPWAP_ELEMENT_ADDSTATION_VENDOR 0
#define CAPWAP_ELEMENT_ADDSTATION_TYPE 8
#define CAPWAP_ELEMENT_ADDSTATION (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_ADDSTATION_VENDOR, .type = CAPWAP_ELEMENT_ADDSTATION_TYPE }
#define CAPWAP_ADDSTATION_VLAN_MAX_LENGTH 512
struct capwap_addstation_element {
uint8_t radioid;
uint8_t length;
uint8_t* address;
uint8_t* vlan;
};
extern const struct capwap_message_elements_ops capwap_element_addstation_ops;
#endif /* __CAPWAP_ELEMENT_ADD_STATION__HEADER__ */

72
lib/element_controlipv4.c Normal file
View File

@ -0,0 +1,72 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| WTP Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 10 for CAPWAP Control IPv4 Address
Length: 6
********************************************************************/
/* */
static void capwap_controlipv4_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_controlipv4_element* element = (struct capwap_controlipv4_element*)data;
ASSERT(data != NULL);
/* */
func->write_block(handle, (uint8_t*)&element->address, sizeof(struct in_addr));
func->write_u16(handle, element->wtpcount);
}
/* */
static void* capwap_controlipv4_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_controlipv4_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 6) {
log_printf(LOG_DEBUG, "Invalid Control IPv4 Address element: underbuffer");
return NULL;
}
/* Retrieve data */
data = (struct capwap_controlipv4_element*)capwap_alloc(sizeof(struct capwap_controlipv4_element));
func->read_block(handle, (uint8_t*)&data->address, sizeof(struct in_addr));
func->read_u16(handle, &data->wtpcount);
return data;
}
/* */
static void* capwap_controlipv4_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_controlipv4_element));
}
/* */
static void capwap_controlipv4_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_controlipv4_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_controlipv4_element_create,
.parse = capwap_controlipv4_element_parsing,
.clone = capwap_controlipv4_element_clone,
.free = capwap_controlipv4_element_free
};

16
lib/element_controlipv4.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__
#define __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__
#define CAPWAP_ELEMENT_CONTROLIPV4_VENDOR 0
#define CAPWAP_ELEMENT_CONTROLIPV4_TYPE 10
#define CAPWAP_ELEMENT_CONTROLIPV4 (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_CONTROLIPV4_VENDOR, .type = CAPWAP_ELEMENT_CONTROLIPV4_TYPE }
struct capwap_controlipv4_element {
struct in_addr address;
uint16_t wtpcount;
};
extern const struct capwap_message_elements_ops capwap_element_controlipv4_ops;
#endif /* __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__ */

78
lib/element_controlipv6.c Normal file
View File

@ -0,0 +1,78 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| WTP Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 11 for CAPWAP Control IPv6 Address
Length: 18
********************************************************************/
/* */
static void capwap_controlipv6_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_controlipv6_element* element = (struct capwap_controlipv6_element*)data;
ASSERT(data != NULL);
/* */
func->write_block(handle, (uint8_t*)&element->address, sizeof(struct in6_addr));
func->write_u16(handle, element->wtpcount);
}
/* */
static void* capwap_controlipv6_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_controlipv6_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 18) {
log_printf(LOG_DEBUG, "Invalid Control IPv6 Address element: underbuffer");
return NULL;
}
/* Retrieve data */
data = (struct capwap_controlipv6_element*)capwap_alloc(sizeof(struct capwap_controlipv6_element));
func->read_block(handle, (uint8_t*)&data->address, sizeof(struct in6_addr));
func->read_u16(handle, &data->wtpcount);
return data;
}
/* */
static void* capwap_controlipv6_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_controlipv6_element));
}
/* */
static void capwap_controlipv6_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
const struct capwap_message_elements_ops capwap_element_controlipv6_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_controlipv6_element_create,
.parse = capwap_controlipv6_element_parsing,
.clone = capwap_controlipv6_element_clone,
.free = capwap_controlipv6_element_free
};

16
lib/element_controlipv6.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef __CAPWAP_ELEMENT_CONTROLIPV6_HEADER__
#define __CAPWAP_ELEMENT_CONTROLIPV6_HEADER__
#define CAPWAP_ELEMENT_CONTROLIPV6_VENDOR 0
#define CAPWAP_ELEMENT_CONTROLIPV6_TYPE 11
#define CAPWAP_ELEMENT_CONTROLIPV6 (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_CONTROLIPV6_VENDOR, .type = CAPWAP_ELEMENT_CONTROLIPV6_TYPE }
struct capwap_controlipv6_element {
struct in6_addr address;
unsigned short wtpcount;
};
extern const struct capwap_message_elements_ops capwap_element_controlipv6_ops;
#endif /* __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__ */

View File

@ -0,0 +1,114 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data Type | Data Mode | Data Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data ....
+-+-+-+-+-+-+-+-+
Type: 13 for Data Transfer Data
Length: >= 5
********************************************************************/
/* */
static void capwap_datatransferdata_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_datatransferdata_element* element = (struct capwap_datatransferdata_element*)data;
ASSERT(data != NULL);
ASSERT((element->type == CAPWAP_DATATRANSFERDATA_TYPE_DATA_IS_INCLUDED) || (element->type == CAPWAP_DATATRANSFERDATA_TYPE_DATA_EOF) || (element->type == CAPWAP_DATATRANSFERDATA_TYPE_ERROR));
ASSERT((element->mode == CAPWAP_DATATRANSFERDATA_MODE_CRASH_DUMP) || (element->mode == CAPWAP_DATATRANSFERDATA_MODE_MEMORY_DUMP));
ASSERT(element->length > 0);
func->write_u8(handle, element->type);
func->write_u8(handle, element->mode);
func->write_u16(handle, element->length);
func->write_block(handle, element->data, element->length);
}
/* */
static void* capwap_datatransferdata_element_clone(void* data) {
struct capwap_datatransferdata_element* cloneelement;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_datatransferdata_element));
if (cloneelement->length > 0) {
cloneelement->data = capwap_clone(((struct capwap_datatransferdata_element*)data)->data, cloneelement->length);
}
return cloneelement;
}
/* */
static void capwap_datatransferdata_element_free(void* data) {
struct capwap_datatransferdata_element* element = (struct capwap_datatransferdata_element*)data;
ASSERT(data != NULL);
if (element->data) {
capwap_free(element->data);
}
capwap_free(data);
}
/* */
static void* capwap_datatransferdata_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
unsigned short length;
struct capwap_datatransferdata_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 5) {
log_printf(LOG_DEBUG, "Invalid Data Transfer Data element: underbuffer");
return NULL;
}
length -= 4;
/* */
data = (struct capwap_datatransferdata_element*)capwap_alloc(sizeof(struct capwap_datatransferdata_element));
memset(data, 0, sizeof(struct capwap_datatransferdata_element));
/* Retrieve data */
func->read_u8(handle, &data->type);
func->read_u8(handle, &data->mode);
func->read_u16(handle, &data->length);
if ((data->type != CAPWAP_DATATRANSFERDATA_TYPE_DATA_IS_INCLUDED) && (data->type != CAPWAP_DATATRANSFERDATA_TYPE_DATA_EOF) && (data->type != CAPWAP_DATATRANSFERDATA_TYPE_ERROR)) {
capwap_datatransferdata_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Data Transfer Data element: invalid type");
return NULL;
} else if ((data->mode != CAPWAP_DATATRANSFERDATA_MODE_CRASH_DUMP) && (data->mode != CAPWAP_DATATRANSFERDATA_MODE_MEMORY_DUMP)) {
capwap_datatransferdata_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Data Transfer Data element: invalid mode");
return NULL;
} else if (length != data->length) {
capwap_datatransferdata_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Data Transfer Data element: invalid length");
return NULL;
}
data->data = (uint8_t*)capwap_alloc(length);
func->read_block(handle, data->data, length);
return data;
}
/* */
const struct capwap_message_elements_ops capwap_element_datatransferdata_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_datatransferdata_element_create,
.parse = capwap_datatransferdata_element_parsing,
.clone = capwap_datatransferdata_element_clone,
.free = capwap_datatransferdata_element_free
};

View File

@ -0,0 +1,25 @@
#ifndef __CAPWAP_ELEMENT_DATA_TRANSFER_DATA_HEADER__
#define __CAPWAP_ELEMENT_DATA_TRANSFER_DATA_HEADER__
#define CAPWAP_ELEMENT_DATATRANSFERDATA_VENDOR 0
#define CAPWAP_ELEMENT_DATATRANSFERDATA_TYPE 13
#define CAPWAP_ELEMENT_DATATRANSFERDATA (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_DATATRANSFERDATA_VENDOR, .type = CAPWAP_ELEMENT_DATATRANSFERDATA_TYPE }
#define CAPWAP_DATATRANSFERDATA_TYPE_DATA_IS_INCLUDED 1
#define CAPWAP_DATATRANSFERDATA_TYPE_DATA_EOF 2
#define CAPWAP_DATATRANSFERDATA_TYPE_ERROR 5
#define CAPWAP_DATATRANSFERDATA_MODE_CRASH_DUMP 1
#define CAPWAP_DATATRANSFERDATA_MODE_MEMORY_DUMP 2
struct capwap_datatransferdata_element {
uint8_t type;
uint8_t mode;
uint16_t length;
uint8_t* data;
};
extern const struct capwap_message_elements_ops capwap_element_datatransferdata_ops;
#endif /* __CAPWAP_ELEMENT_DATA_TRANSFER_DATA_HEADER__ */

View File

@ -0,0 +1,74 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
| Data Mode |
+-+-+-+-+-+-+-+-+
Type: 14 for Data Transfer Mode
Length: 1
********************************************************************/
/* */
static void capwap_datatransfermode_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_datatransfermode_element* element = (struct capwap_datatransfermode_element*)data;
ASSERT(data != NULL);
ASSERT((element->mode == CAPWAP_DATATRANSFERMODE_MODE_CRASH_DUMP) || (element->mode == CAPWAP_DATATRANSFERMODE_MODE_MEMORY_DUMP));
/* */
func->write_u8(handle, element->mode);
}
/* */
static void* capwap_datatransfermode_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_datatransfermode_element));
}
/* */
static void capwap_datatransfermode_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
static void* capwap_datatransfermode_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_datatransfermode_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 1) {
log_printf(LOG_DEBUG, "Invalid Data Transfer Mode element: underbuffer");
return NULL;
}
/* Retrieve data */
data = (struct capwap_datatransfermode_element*)capwap_alloc(sizeof(struct capwap_datatransfermode_element));
func->read_u8(handle, &data->mode);
if ((data->mode != CAPWAP_DATATRANSFERMODE_MODE_CRASH_DUMP) && (data->mode != CAPWAP_DATATRANSFERMODE_MODE_MEMORY_DUMP)) {
capwap_datatransfermode_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Data Transfer Mode element: invalid mode");
return NULL;
}
return data;
}
/* */
const struct capwap_message_elements_ops capwap_element_datatransfermode_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_datatransfermode_element_create,
.parse = capwap_datatransfermode_element_parsing,
.clone = capwap_datatransfermode_element_clone,
.free = capwap_datatransfermode_element_free
};

View File

@ -0,0 +1,18 @@
#ifndef __CAPWAP_ELEMENT_DATA_TRANSFER_MODE_HEADER__
#define __CAPWAP_ELEMENT_DATA_TRANSFER_MODE_HEADER__
#define CAPWAP_ELEMENT_DATATRANSFERMODE_VENDOR 0
#define CAPWAP_ELEMENT_DATATRANSFERMODE_TYPE 14
#define CAPWAP_ELEMENT_DATATRANSFERMODE (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_DATATRANSFERMODE_VENDOR, .type = CAPWAP_ELEMENT_DATATRANSFERMODE_TYPE }
#define CAPWAP_DATATRANSFERMODE_MODE_CRASH_DUMP 1
#define CAPWAP_DATATRANSFERMODE_MODE_MEMORY_DUMP 2
struct capwap_datatransfermode_element {
uint8_t mode;
};
extern const struct capwap_message_elements_ops capwap_element_datatransfermode_ops;
#endif /* __CAPWAP_ELEMENT_DATA_TRANSFER_MODE_HEADER__ */

View File

@ -0,0 +1,118 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID |Num Of Entries | Length | MAC Address...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 15 for Decryption Error Report
Length: >= 9
********************************************************************/
/* */
static void capwap_decrypterrorreport_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_decrypterrorreport_element* element = (struct capwap_decrypterrorreport_element*)data;
ASSERT(data != NULL);
ASSERT(IS_VALID_RADIOID(element->radioid));
ASSERT(element->entry > 0);
ASSERT(IS_VALID_MACADDRESS_LENGTH(element->length));
func->write_u8(handle, element->radioid);
func->write_u8(handle, element->entry);
func->write_u8(handle, element->length);
func->write_block(handle, element->address, element->entry * element->length);
}
/* */
static void* capwap_decrypterrorreport_element_clone(void* data) {
struct capwap_decrypterrorreport_element* cloneelement;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_decrypterrorreport_element));
if (cloneelement->entry > 0) {
cloneelement->address = capwap_clone(((struct capwap_decrypterrorreport_element*)data)->address, cloneelement->entry * cloneelement->length);
}
return cloneelement;
}
/* */
static void capwap_decrypterrorreport_element_free(void* data) {
struct capwap_decrypterrorreport_element* element = (struct capwap_decrypterrorreport_element*)data;
ASSERT(data != NULL);
if (element->address) {
capwap_free(element->address);
}
capwap_free(data);
}
/* */
static void* capwap_decrypterrorreport_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
unsigned short length;
struct capwap_decrypterrorreport_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
length = func->read_ready(handle);
if (length < 9) {
log_printf(LOG_DEBUG, "Invalid Decryption Error Report element: underbuffer");
return NULL;
}
length -= 3;
/* */
data = (struct capwap_decrypterrorreport_element*)capwap_alloc(sizeof(struct capwap_decrypterrorreport_element));
memset(data, 0, sizeof(struct capwap_decrypterrorreport_element));
/* Retrieve data */
func->read_u8(handle, &data->radioid);
func->read_u8(handle, &data->entry);
func->read_u8(handle, &data->length);
if (!IS_VALID_RADIOID(data->radioid)) {
capwap_decrypterrorreport_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Decryption Error Report element: invalid radioid");
return NULL;
} else if (!data->entry) {
capwap_decrypterrorreport_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Decryption Error Report element: invalid entry");
return NULL;
} else if (!IS_VALID_MACADDRESS_LENGTH(data->length)) {
capwap_decrypterrorreport_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Decryption Error Report element: invalid length");
return NULL;
}
if (length != (data->entry * data->length)) {
capwap_decrypterrorreport_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Decryption Error Report element: invalid total length");
return NULL;
}
data->address = (uint8_t*)capwap_alloc(length);
func->read_block(handle, data->address, length);
return data;
}
/* */
const struct capwap_message_elements_ops capwap_element_decrypterrorreport_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_decrypterrorreport_element_create,
.parse = capwap_decrypterrorreport_element_parsing,
.clone = capwap_decrypterrorreport_element_clone,
.free = capwap_decrypterrorreport_element_free
};

View File

@ -0,0 +1,18 @@
#ifndef __CAPWAP_ELEMENT_DECRYPT_ERROR_REPORT__HEADER__
#define __CAPWAP_ELEMENT_DECRYPT_ERROR_REPORT__HEADER__
#define CAPWAP_ELEMENT_DECRYPTERRORREPORT_VENDOR 0
#define CAPWAP_ELEMENT_DECRYPTERRORREPORT_TYPE 15
#define CAPWAP_ELEMENT_DECRYPTERRORREPORT (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_DECRYPTERRORREPORT_VENDOR, .type = CAPWAP_ELEMENT_DECRYPTERRORREPORT_TYPE }
struct capwap_decrypterrorreport_element {
uint8_t radioid;
uint8_t entry;
uint8_t length;
uint8_t* address;
};
extern const struct capwap_message_elements_ops capwap_element_decrypterrorreport_ops;
#endif /* __CAPWAP_ELEMENT_DECRYPT_ERROR_REPORT__HEADER__ */

View File

@ -0,0 +1,77 @@
#include "capwap.h"
#include "element.h"
/********************************************************************
0 1 2
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Radio ID | Report Interval |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 16 for Decryption Error Report Period
Length: 3
********************************************************************/
/* */
static void capwap_decrypterrorreportperiod_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_decrypterrorreportperiod_element* element = (struct capwap_decrypterrorreportperiod_element*)data;
ASSERT(data != NULL);
ASSERT(IS_VALID_RADIOID(element->radioid));
/* */
func->write_u8(handle, element->radioid);
func->write_u16(handle, element->interval);
}
/* */
static void* capwap_decrypterrorreportperiod_element_clone(void* data) {
ASSERT(data != NULL);
return capwap_clone(data, sizeof(struct capwap_decrypterrorreportperiod_element));
}
/* */
static void capwap_decrypterrorreportperiod_element_free(void* data) {
ASSERT(data != NULL);
capwap_free(data);
}
/* */
static void* capwap_decrypterrorreportperiod_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
struct capwap_decrypterrorreportperiod_element* data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) != 3) {
log_printf(LOG_DEBUG, "Invalid Decryption Error Report Period element: underbuffer");
return NULL;
}
/* Retrieve data */
data = (struct capwap_decrypterrorreportperiod_element*)capwap_alloc(sizeof(struct capwap_decrypterrorreportperiod_element));
func->read_u8(handle, &data->radioid);
func->read_u16(handle, &data->interval);
if (!IS_VALID_RADIOID(data->radioid)) {
capwap_decrypterrorreportperiod_element_free((void*)data);
log_printf(LOG_DEBUG, "Invalid Decryption Error Report Period element: invalid radioid");
return NULL;
}
return data;
}
/* */
const struct capwap_message_elements_ops capwap_element_decrypterrorreportperiod_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
.create = capwap_decrypterrorreportperiod_element_create,
.parse = capwap_decrypterrorreportperiod_element_parsing,
.clone = capwap_decrypterrorreportperiod_element_clone,
.free = capwap_decrypterrorreportperiod_element_free
};

Some files were not shown because too many files have changed in this diff Show More