fork SmartCAWPAP as FreeWTP
This commit is contained in:
218
lib/Makefile.am
Executable file
218
lib/Makefile.am
Executable 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
91
lib/array.c
Normal 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
17
lib/array.h
Normal 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__ */
|
790
lib/binding/ieee80211/ieee80211.c
Normal file
790
lib/binding/ieee80211/ieee80211.c
Normal 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);
|
||||
}
|
751
lib/binding/ieee80211/ieee80211.h
Normal file
751
lib/binding/ieee80211/ieee80211.h
Normal 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
93
lib/capwap.c
Normal 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
90
lib/capwap.h
Normal 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
29
lib/capwap_dfa.h
Normal 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
178
lib/debug.c
Normal 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
39
lib/debug.h
Normal 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
33
lib/dfa.c
Normal 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
634
lib/dtls.c
Normal 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
107
lib/dtls.h
Normal 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
680
lib/element.c
Normal 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
169
lib/element.h
Normal 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
162
lib/element_80211_addwlan.c
Normal 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
|
||||
};
|
67
lib/element_80211_addwlan.h
Normal file
67
lib/element_80211_addwlan.h
Normal 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
151
lib/element_80211_antenna.c
Normal 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
|
||||
};
|
32
lib/element_80211_antenna.h
Normal file
32
lib/element_80211_antenna.h
Normal 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__ */
|
76
lib/element_80211_assignbssid.c
Normal file
76
lib/element_80211_assignbssid.c
Normal 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
|
||||
};
|
17
lib/element_80211_assignbssid.h
Normal file
17
lib/element_80211_assignbssid.h
Normal 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__ */
|
72
lib/element_80211_deletewlan.c
Normal file
72
lib/element_80211_deletewlan.c
Normal 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
|
||||
};
|
16
lib/element_80211_deletewlan.h
Normal file
16
lib/element_80211_deletewlan.h
Normal 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__ */
|
88
lib/element_80211_directsequencecontrol.c
Normal file
88
lib/element_80211_directsequencecontrol.c
Normal 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
|
||||
};
|
25
lib/element_80211_directsequencecontrol.h
Normal file
25
lib/element_80211_directsequencecontrol.h
Normal 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
92
lib/element_80211_ie.c
Normal 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
22
lib/element_80211_ie.h
Normal 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__ */
|
89
lib/element_80211_mac_profile.c
Normal file
89
lib/element_80211_mac_profile.c
Normal 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
|
||||
};
|
18
lib/element_80211_mac_profile.h
Normal file
18
lib/element_80211_mac_profile.h
Normal 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__ */
|
91
lib/element_80211_macoperation.c
Normal file
91
lib/element_80211_macoperation.c
Normal 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
|
||||
};
|
21
lib/element_80211_macoperation.h
Normal file
21
lib/element_80211_macoperation.h
Normal 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__ */
|
76
lib/element_80211_miccountermeasures.c
Normal file
76
lib/element_80211_miccountermeasures.c
Normal 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
|
||||
};
|
17
lib/element_80211_miccountermeasures.h
Normal file
17
lib/element_80211_miccountermeasures.h
Normal 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__ */
|
81
lib/element_80211_multidomaincapability.c
Normal file
81
lib/element_80211_multidomaincapability.c
Normal 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
|
||||
};
|
18
lib/element_80211_multidomaincapability.h
Normal file
18
lib/element_80211_multidomaincapability.h
Normal 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__ */
|
81
lib/element_80211_ofdmcontrol.c
Normal file
81
lib/element_80211_ofdmcontrol.c
Normal 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
|
||||
};
|
27
lib/element_80211_ofdmcontrol.h
Normal file
27
lib/element_80211_ofdmcontrol.h
Normal 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__ */
|
81
lib/element_80211_rateset.c
Normal file
81
lib/element_80211_rateset.c
Normal 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
|
||||
};
|
20
lib/element_80211_rateset.h
Normal file
20
lib/element_80211_rateset.h
Normal 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__ */
|
109
lib/element_80211_rsnaerrorreport.c
Normal file
109
lib/element_80211_rsnaerrorreport.c
Normal 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
|
||||
};
|
24
lib/element_80211_rsnaerrorreport.h
Normal file
24
lib/element_80211_rsnaerrorreport.h
Normal 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__ */
|
97
lib/element_80211_station.c
Normal file
97
lib/element_80211_station.c
Normal 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
|
||||
};
|
24
lib/element_80211_station.h
Normal file
24
lib/element_80211_station.h
Normal 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__ */
|
108
lib/element_80211_stationkey.c
Normal file
108
lib/element_80211_stationkey.c
Normal 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
|
||||
};
|
26
lib/element_80211_stationkey.h
Normal file
26
lib/element_80211_stationkey.h
Normal 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__ */
|
76
lib/element_80211_stationqos.c
Normal file
76
lib/element_80211_stationqos.c
Normal 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
|
||||
};
|
16
lib/element_80211_stationqos.h
Normal file
16
lib/element_80211_stationqos.h
Normal 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__ */
|
149
lib/element_80211_statistics.c
Normal file
149
lib/element_80211_statistics.c
Normal 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
|
||||
};
|
34
lib/element_80211_statistics.h
Normal file
34
lib/element_80211_statistics.h
Normal 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__ */
|
102
lib/element_80211_supported_mac_profiles.c
Normal file
102
lib/element_80211_supported_mac_profiles.c
Normal 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
|
||||
};
|
20
lib/element_80211_supported_mac_profiles.h
Normal file
20
lib/element_80211_supported_mac_profiles.h
Normal 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__ */
|
81
lib/element_80211_supportedrates.c
Normal file
81
lib/element_80211_supportedrates.c
Normal 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
|
||||
};
|
20
lib/element_80211_supportedrates.h
Normal file
20
lib/element_80211_supportedrates.h
Normal 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__ */
|
75
lib/element_80211_txpower.c
Normal file
75
lib/element_80211_txpower.c
Normal 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
|
||||
};
|
16
lib/element_80211_txpower.h
Normal file
16
lib/element_80211_txpower.h
Normal 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__ */
|
96
lib/element_80211_txpowerlevel.c
Normal file
96
lib/element_80211_txpowerlevel.c
Normal 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
|
||||
};
|
19
lib/element_80211_txpowerlevel.h
Normal file
19
lib/element_80211_txpowerlevel.h
Normal 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__ */
|
92
lib/element_80211_updatestationqos.c
Normal file
92
lib/element_80211_updatestationqos.c
Normal 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
|
||||
};
|
27
lib/element_80211_updatestationqos.h
Normal file
27
lib/element_80211_updatestationqos.h
Normal 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__ */
|
113
lib/element_80211_updatewlan.c
Normal file
113
lib/element_80211_updatewlan.c
Normal 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
|
||||
};
|
42
lib/element_80211_updatewlan.h
Normal file
42
lib/element_80211_updatewlan.h
Normal 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
100
lib/element_80211_wtpqos.c
Normal 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
|
||||
};
|
37
lib/element_80211_wtpqos.h
Normal file
37
lib/element_80211_wtpqos.h
Normal 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__ */
|
88
lib/element_80211_wtpradioconf.c
Normal file
88
lib/element_80211_wtpradioconf.c
Normal 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
|
||||
};
|
26
lib/element_80211_wtpradioconf.h
Normal file
26
lib/element_80211_wtpradioconf.h
Normal 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__ */
|
76
lib/element_80211_wtpradiofailalarm.c
Normal file
76
lib/element_80211_wtpradiofailalarm.c
Normal 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
|
||||
};
|
21
lib/element_80211_wtpradiofailalarm.h
Normal file
21
lib/element_80211_wtpradiofailalarm.h
Normal 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__ */
|
75
lib/element_80211_wtpradioinformation.c
Normal file
75
lib/element_80211_wtpradioinformation.c
Normal 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
|
||||
};
|
22
lib/element_80211_wtpradioinformation.h
Normal file
22
lib/element_80211_wtpradioinformation.h
Normal 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__ */
|
93
lib/element_80211n_radioconf.c
Normal file
93
lib/element_80211n_radioconf.c
Normal 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
|
||||
};
|
28
lib/element_80211n_radioconf.h
Normal file
28
lib/element_80211n_radioconf.h
Normal 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__ */
|
102
lib/element_80211n_station_information.c
Normal file
102
lib/element_80211n_station_information.c
Normal 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
|
||||
};
|
32
lib/element_80211n_station_information.h
Normal file
32
lib/element_80211n_station_information.h
Normal 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
207
lib/element_acdescriptor.c
Normal 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
|
||||
};
|
44
lib/element_acdescriptor.h
Normal file
44
lib/element_acdescriptor.h
Normal 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
91
lib/element_acipv4list.c
Normal 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
17
lib/element_acipv4list.h
Normal 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
97
lib/element_acipv6list.c
Normal 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
17
lib/element_acipv6list.h
Normal 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
85
lib/element_acname.c
Normal 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
17
lib/element_acname.h
Normal 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__ */
|
86
lib/element_acnamepriority.c
Normal file
86
lib/element_acnamepriority.c
Normal 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
|
||||
};
|
18
lib/element_acnamepriority.h
Normal file
18
lib/element_acnamepriority.h
Normal 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
68
lib/element_actimestamp.c
Normal 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
16
lib/element_actimestamp.h
Normal 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
111
lib/element_addmacacl.c
Normal 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
17
lib/element_addmacacl.h
Normal 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
135
lib/element_addstation.c
Normal 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
20
lib/element_addstation.h
Normal 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
72
lib/element_controlipv4.c
Normal 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
16
lib/element_controlipv4.h
Normal 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
78
lib/element_controlipv6.c
Normal 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
16
lib/element_controlipv6.h
Normal 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__ */
|
114
lib/element_datatransferdata.c
Normal file
114
lib/element_datatransferdata.c
Normal 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
|
||||
};
|
25
lib/element_datatransferdata.h
Normal file
25
lib/element_datatransferdata.h
Normal 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__ */
|
74
lib/element_datatransfermode.c
Normal file
74
lib/element_datatransfermode.c
Normal 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
|
||||
};
|
18
lib/element_datatransfermode.h
Normal file
18
lib/element_datatransfermode.h
Normal 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__ */
|
118
lib/element_decrypterrorreport.c
Normal file
118
lib/element_decrypterrorreport.c
Normal 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
|
||||
};
|
18
lib/element_decrypterrorreport.h
Normal file
18
lib/element_decrypterrorreport.h
Normal 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__ */
|
77
lib/element_decrypterrorreportperiod.c
Normal file
77
lib/element_decrypterrorreportperiod.c
Normal 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
Reference in New Issue
Block a user