remove dos style newlines
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,54 +1,54 @@
|
||||
#ifndef __CAPWAP_HASH_HEADER__
|
||||
#define __CAPWAP_HASH_HEADER__
|
||||
|
||||
typedef unsigned long (*capwap_hash_item_gethash)(const void* key, unsigned long hashsize);
|
||||
typedef const void* (*capwap_hash_item_getkey)(const void* data);
|
||||
typedef int (*capwap_hash_item_cmp)(const void* key1, const void* key2);
|
||||
typedef void (*capwap_hash_item_free)(void* data);
|
||||
|
||||
#define HASH_BREAK 0
|
||||
#define HASH_CONTINUE 1
|
||||
#define HASH_DELETE_AND_BREAK 2
|
||||
#define HASH_DELETE_AND_CONTINUE 3
|
||||
typedef int (*capwap_hash_item_foreach)(void* data, void* param);
|
||||
|
||||
struct capwap_hash_item {
|
||||
void* data;
|
||||
|
||||
int height;
|
||||
|
||||
struct capwap_hash_item* parent;
|
||||
struct capwap_hash_item* left;
|
||||
struct capwap_hash_item* right;
|
||||
|
||||
struct capwap_hash_item* removenext;
|
||||
};
|
||||
|
||||
struct capwap_hash {
|
||||
struct capwap_hash_item** items;
|
||||
unsigned long hashsize;
|
||||
|
||||
/* */
|
||||
unsigned long count;
|
||||
|
||||
/* */
|
||||
struct capwap_hash_item* removeitems;
|
||||
|
||||
/* Callback functions */
|
||||
capwap_hash_item_gethash item_gethash;
|
||||
capwap_hash_item_getkey item_getkey;
|
||||
capwap_hash_item_cmp item_cmp;
|
||||
capwap_hash_item_free item_free;
|
||||
};
|
||||
|
||||
struct capwap_hash* capwap_hash_create(unsigned long hashsize);
|
||||
void capwap_hash_free(struct capwap_hash* hash);
|
||||
|
||||
void capwap_hash_add(struct capwap_hash* hash, void* data);
|
||||
void capwap_hash_delete(struct capwap_hash* hash, const void* key);
|
||||
void capwap_hash_deleteall(struct capwap_hash* hash);
|
||||
|
||||
void* capwap_hash_search(struct capwap_hash* hash, const void* key);
|
||||
void capwap_hash_foreach(struct capwap_hash* hash, capwap_hash_item_foreach item_foreach, void* param);
|
||||
|
||||
#endif /* __CAPWAP_HASH_HEADER__ */
|
||||
#ifndef __CAPWAP_HASH_HEADER__
|
||||
#define __CAPWAP_HASH_HEADER__
|
||||
|
||||
typedef unsigned long (*capwap_hash_item_gethash)(const void* key, unsigned long hashsize);
|
||||
typedef const void* (*capwap_hash_item_getkey)(const void* data);
|
||||
typedef int (*capwap_hash_item_cmp)(const void* key1, const void* key2);
|
||||
typedef void (*capwap_hash_item_free)(void* data);
|
||||
|
||||
#define HASH_BREAK 0
|
||||
#define HASH_CONTINUE 1
|
||||
#define HASH_DELETE_AND_BREAK 2
|
||||
#define HASH_DELETE_AND_CONTINUE 3
|
||||
typedef int (*capwap_hash_item_foreach)(void* data, void* param);
|
||||
|
||||
struct capwap_hash_item {
|
||||
void* data;
|
||||
|
||||
int height;
|
||||
|
||||
struct capwap_hash_item* parent;
|
||||
struct capwap_hash_item* left;
|
||||
struct capwap_hash_item* right;
|
||||
|
||||
struct capwap_hash_item* removenext;
|
||||
};
|
||||
|
||||
struct capwap_hash {
|
||||
struct capwap_hash_item** items;
|
||||
unsigned long hashsize;
|
||||
|
||||
/* */
|
||||
unsigned long count;
|
||||
|
||||
/* */
|
||||
struct capwap_hash_item* removeitems;
|
||||
|
||||
/* Callback functions */
|
||||
capwap_hash_item_gethash item_gethash;
|
||||
capwap_hash_item_getkey item_getkey;
|
||||
capwap_hash_item_cmp item_cmp;
|
||||
capwap_hash_item_free item_free;
|
||||
};
|
||||
|
||||
struct capwap_hash* capwap_hash_create(unsigned long hashsize);
|
||||
void capwap_hash_free(struct capwap_hash* hash);
|
||||
|
||||
void capwap_hash_add(struct capwap_hash* hash, void* data);
|
||||
void capwap_hash_delete(struct capwap_hash* hash, const void* key);
|
||||
void capwap_hash_deleteall(struct capwap_hash* hash);
|
||||
|
||||
void* capwap_hash_search(struct capwap_hash* hash, const void* key);
|
||||
void capwap_hash_foreach(struct capwap_hash* hash, capwap_hash_item_foreach item_foreach, void* param);
|
||||
|
||||
#endif /* __CAPWAP_HASH_HEADER__ */
|
||||
|
@ -1,236 +1,236 @@
|
||||
#ifndef __CAPWAP_RFC_HEADER__
|
||||
#define __CAPWAP_RFC_HEADER__
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifndef STRUCT_PACKED
|
||||
#define STRUCT_PACKED __attribute__((__packed__))
|
||||
#endif
|
||||
|
||||
#define CAPWAP_PROTOCOL_VERSION 0
|
||||
|
||||
#define CAPWAP_MTU_DEFAULT 1400
|
||||
#define CAPWAP_DONT_FRAGMENT 0
|
||||
|
||||
/* Capwap preamble */
|
||||
#define CAPWAP_PREAMBLE_HEADER 0
|
||||
#define CAPWAP_PREAMBLE_DTLS_HEADER 1
|
||||
|
||||
struct capwap_preamble {
|
||||
#ifdef CAPWAP_BIG_ENDIAN
|
||||
uint8_t version : 4;
|
||||
uint8_t type : 4;
|
||||
#else
|
||||
uint8_t type : 4;
|
||||
uint8_t version : 4;
|
||||
#endif
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Capwap DTLS header */
|
||||
struct capwap_dtls_header {
|
||||
struct capwap_preamble preamble;
|
||||
uint8_t reserved1;
|
||||
uint8_t reserved2;
|
||||
uint8_t reserved3;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Capwap header: 8 (header) + 12 (radio mac) + 256 (wireless info) */
|
||||
#define CAPWAP_HEADER_MAX_SIZE 276
|
||||
struct capwap_header {
|
||||
struct capwap_preamble preamble;
|
||||
#ifdef CAPWAP_BIG_ENDIAN
|
||||
uint16_t hlen : 5;
|
||||
uint16_t rid : 5;
|
||||
uint16_t wbid : 5;
|
||||
uint16_t flag_t : 1;
|
||||
uint8_t flag_f : 1;
|
||||
uint8_t flag_l : 1;
|
||||
uint8_t flag_w : 1;
|
||||
uint8_t flag_m : 1;
|
||||
uint8_t flag_k : 1;
|
||||
uint8_t flag_res : 3;
|
||||
#else
|
||||
uint16_t _rid_hi : 3;
|
||||
uint16_t hlen : 5;
|
||||
uint16_t flag_t : 1;
|
||||
uint16_t wbid : 5;
|
||||
uint16_t _rid_lo : 2;
|
||||
uint8_t flag_res : 3;
|
||||
uint8_t flag_k : 1;
|
||||
uint8_t flag_m : 1;
|
||||
uint8_t flag_w : 1;
|
||||
uint8_t flag_l : 1;
|
||||
uint8_t flag_f : 1;
|
||||
#endif
|
||||
uint16_t frag_id;
|
||||
uint16_t frag_off; /* Only first 13 bit */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define FRAGMENT_OFFSET_MASK 0xfff8
|
||||
|
||||
/* Mac Address */
|
||||
struct capwap_mac_address {
|
||||
uint8_t length;
|
||||
uint8_t address[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Wireless Information */
|
||||
struct capwap_wireless_information {
|
||||
uint8_t length;
|
||||
uint8_t data[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* IEEE802.11 Wireless Information */
|
||||
struct capwap_ieee80211_frame_info {
|
||||
uint8_t rssi;
|
||||
uint8_t snr;
|
||||
uint16_t rate;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Message element */
|
||||
struct capwap_message_element {
|
||||
uint16_t type;
|
||||
uint16_t length;
|
||||
uint8_t data[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Control Message Type */
|
||||
#define CAPWAP_FIRST_MESSAGE_TYPE 1
|
||||
#define CAPWAP_DISCOVERY_REQUEST 1
|
||||
#define CAPWAP_DISCOVERY_RESPONSE 2
|
||||
#define CAPWAP_JOIN_REQUEST 3
|
||||
#define CAPWAP_JOIN_RESPONSE 4
|
||||
#define CAPWAP_CONFIGURATION_STATUS_REQUEST 5
|
||||
#define CAPWAP_CONFIGURATION_STATUS_RESPONSE 6
|
||||
#define CAPWAP_CONFIGURATION_UPDATE_REQUEST 7
|
||||
#define CAPWAP_CONFIGURATION_UPDATE_RESPONSE 8
|
||||
#define CAPWAP_WTP_EVENT_REQUEST 9
|
||||
#define CAPWAP_WTP_EVENT_RESPONSE 10
|
||||
#define CAPWAP_CHANGE_STATE_EVENT_REQUEST 11
|
||||
#define CAPWAP_CHANGE_STATE_EVENT_RESPONSE 12
|
||||
#define CAPWAP_ECHO_REQUEST 13
|
||||
#define CAPWAP_ECHO_RESPONSE 14
|
||||
#define CAPWAP_IMAGE_DATA_REQUEST 15
|
||||
#define CAPWAP_IMAGE_DATA_RESPONSE 16
|
||||
#define CAPWAP_RESET_REQUEST 17
|
||||
#define CAPWAP_RESET_RESPONSE 18
|
||||
#define CAPWAP_PRIMARY_DISCOVERY_REQUEST 19
|
||||
#define CAPWAP_PRIMARY_DISCOVERY_RESPONSE 20
|
||||
#define CAPWAP_DATA_TRANSFER_REQUEST 21
|
||||
#define CAPWAP_DATA_TRANSFER_RESPONSE 22
|
||||
#define CAPWAP_CLEAR_CONFIGURATION_REQUEST 23
|
||||
#define CAPWAP_CLEAR_CONFIGURATION_RESPONSE 24
|
||||
#define CAPWAP_STATION_CONFIGURATION_REQUEST 25
|
||||
#define CAPWAP_STATION_CONFIGURATION_RESPONSE 26
|
||||
#define CAPWAP_LAST_MESSAGE_TYPE 26
|
||||
#define CAPWAP_VALID_MESSAGE_TYPE(x) (((x) >= CAPWAP_FIRST_MESSAGE_TYPE) && ((x) <= CAPWAP_LAST_MESSAGE_TYPE))
|
||||
|
||||
#define CAPWAP_IEEE80211_FIRST_MESSAGE_TYPE 3398913
|
||||
#define CAPWAP_IEEE80211_WLAN_CONFIGURATION_REQUEST 3398913
|
||||
#define CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE 3398914
|
||||
#define CAPWAP_IEEE80211_LAST_MESSAGE_TYPE 3398914
|
||||
#define CAPWAP_VALID_IEEE80211_MESSAGE_TYPE(x) (((x) >= CAPWAP_IEEE80211_FIRST_MESSAGE_TYPE) && ((x) <= CAPWAP_IEEE80211_LAST_MESSAGE_TYPE))
|
||||
|
||||
/* Control Message */
|
||||
#define CAPWAP_CONTROL_MESSAGE_MIN_LENGTH 3
|
||||
|
||||
struct capwap_control_message {
|
||||
uint32_t type;
|
||||
uint8_t seq;
|
||||
uint16_t length;
|
||||
uint8_t flags;
|
||||
uint8_t elements[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Data Message Keep-Alive*/
|
||||
#define CAPWAP_DATA_MESSAGE_KEEPALIVE_MIN_LENGTH 2
|
||||
|
||||
struct capwap_data_message {
|
||||
uint16_t length;
|
||||
uint8_t elements[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Capwap dtls header helper */
|
||||
#define GET_DTLS_BODY(x) (void*)(((uint8_t*)(x)) + sizeof(struct capwap_dtls_header))
|
||||
|
||||
/* Capwap header helper */
|
||||
#define GET_VERSION_HEADER(x) ((x)->preamble.version)
|
||||
#define SET_VERSION_HEADER(x, y) ((x)->preamble.version = (uint8_t)(y))
|
||||
#define GET_TYPE_HEADER(x) ((x)->preamble.type)
|
||||
#define SET_TYPE_HEADER(x, y) ((x)->preamble.type = (uint8_t)(y))
|
||||
|
||||
#define GET_HLEN_HEADER(x) ((x)->hlen)
|
||||
#define SET_HLEN_HEADER(x, y) ((x)->hlen = (uint16_t)(y))
|
||||
#ifdef CAPWAP_BIG_ENDIAN
|
||||
#define GET_RID_HEADER(x) ((uint8_t)((x)->rid))
|
||||
#define SET_RID_HEADER(x, y) ((x)->rid = (uint16_t)(y))
|
||||
#else
|
||||
#define GET_RID_HEADER(x) ((uint8_t)((uint16_t)((x)->_rid_hi << 2 | (x)->_rid_lo)))
|
||||
#define SET_RID_HEADER(x, y) ({ (x)->_rid_hi = (uint16_t)((y) >> 2); (x)->_rid_lo = (uint16_t)((y) & 0x0003); })
|
||||
#endif
|
||||
#define GET_WBID_HEADER(x) ((x)->wbid)
|
||||
#define SET_WBID_HEADER(x, y) ((x)->wbid = (uint16_t)(y))
|
||||
|
||||
#define IS_FLAG_T_HEADER(x) ((x)->flag_t)
|
||||
#define SET_FLAG_T_HEADER(x, y) ((x)->flag_t = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_F_HEADER(x) ((x)->flag_f)
|
||||
#define SET_FLAG_F_HEADER(x, y) ((x)->flag_f = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_L_HEADER(x) ((x)->flag_l)
|
||||
#define SET_FLAG_L_HEADER(x, y) ((x)->flag_l = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_W_HEADER(x) ((x)->flag_w)
|
||||
#define SET_FLAG_W_HEADER(x, y) ((x)->flag_w = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_M_HEADER(x) ((x)->flag_m)
|
||||
#define SET_FLAG_M_HEADER(x, y) ((x)->flag_m = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_K_HEADER(x) ((x)->flag_k)
|
||||
#define SET_FLAG_K_HEADER(x, y) ((x)->flag_k = ((y) ? 1 : 0))
|
||||
|
||||
#define GET_FRAGMENT_ID_HEADER(x) (ntohs((x)->frag_id))
|
||||
#define SET_FRAGMENT_ID_HEADER(x, y) ((x)->frag_id = htons((uint16_t)(y)))
|
||||
#define GET_FRAGMENT_OFFSET_HEADER(x) (ntohs((x)->frag_off) & FRAGMENT_OFFSET_MASK)
|
||||
#define SET_FRAGMENT_OFFSET_HEADER(x, y) ((x)->frag_off &= ~FRAGMENT_OFFSET_MASK, (x)->frag_off |= htons((uint16_t)(y) & FRAGMENT_OFFSET_MASK))
|
||||
|
||||
#define GET_RADIO_MAC_ADDRESS_STRUCT(x) ((struct capwap_mac_address*)(((uint8_t*)(x)) + sizeof(struct capwap_header)))
|
||||
#define GET_WIRELESS_INFORMATION_STRUCT(x) ((struct capwap_wireless_information*)(((uint8_t*)(x)) + sizeof(struct capwap_header) + (IS_FLAG_M_HEADER(x) ? (((GET_RADIO_MAC_ADDRESS_STRUCT(x)->length + sizeof(struct capwap_mac_address)) + 3) / 4) * 4 : 0)))
|
||||
#define GET_PAYLOAD_HEADER(x) ((void*)(((uint8_t*)(x)) + GET_HLEN_HEADER(x) * 4))
|
||||
|
||||
#define IS_SEQUENCE_SMALLER(s1, s2) (((((s1) < (s2)) && (((s2) - (s1)) < 128)) || (((s1) > (s2)) && (((s1) - (s2)) > 128))) ? 1 : 0)
|
||||
|
||||
/* */
|
||||
#define MACADDRESS_NONE_LENGTH 0
|
||||
|
||||
/* */
|
||||
#define MACADDRESS_EUI48_LENGTH 6
|
||||
struct capwap_macaddress_eui48 {
|
||||
uint8_t macaddress[MACADDRESS_EUI48_LENGTH];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* */
|
||||
#define MACADDRESS_EUI64_LENGTH 8
|
||||
struct capwap_macaddress_eui64 {
|
||||
uint8_t macaddress[MACADDRESS_EUI64_LENGTH];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define IS_VALID_MACADDRESS_LENGTH(x) ((x == MACADDRESS_EUI48_LENGTH) || (x == MACADDRESS_EUI64_LENGTH))
|
||||
|
||||
#define RADIOID_MAX_COUNT 31
|
||||
#define IS_VALID_RADIOID(x) ((x >= 1) && (x <= RADIOID_MAX_COUNT))
|
||||
|
||||
#define WLANID_MAX_COUNT 16
|
||||
#define IS_VALID_WLANID(x) ((x >= 1) && (x <= WLANID_MAX_COUNT))
|
||||
|
||||
/* Standard message elements 1 -> 52 (1 - 1023) */
|
||||
#define CAPWAP_MESSAGE_ELEMENTS_START 1
|
||||
#define CAPWAP_MESSAGE_ELEMENTS_STOP 53
|
||||
#define CAPWAP_MESSAGE_ELEMENTS_COUNT ((CAPWAP_MESSAGE_ELEMENTS_STOP - CAPWAP_MESSAGE_ELEMENTS_START) + 1)
|
||||
#define IS_MESSAGE_ELEMENTS(x) (((x >= CAPWAP_MESSAGE_ELEMENTS_START) && (x <= CAPWAP_MESSAGE_ELEMENTS_STOP)) ? 1 : 0)
|
||||
|
||||
/* 802.11 message elements 1024 -> 1024 (1024 - 2047) */
|
||||
#define CAPWAP_80211_MESSAGE_ELEMENTS_START 1024
|
||||
#define CAPWAP_80211_MESSAGE_ELEMENTS_STOP 1048
|
||||
#define CAPWAP_80211_MESSAGE_ELEMENTS_COUNT ((CAPWAP_80211_MESSAGE_ELEMENTS_STOP - CAPWAP_80211_MESSAGE_ELEMENTS_START) + 1)
|
||||
#define IS_80211_MESSAGE_ELEMENTS(x) (((x >= CAPWAP_80211_MESSAGE_ELEMENTS_START) && (x <= CAPWAP_80211_MESSAGE_ELEMENTS_STOP)) ? 1 : 0)
|
||||
|
||||
/* */
|
||||
#define IS_VALID_MESSAGE_ELEMENTS(x) (IS_MESSAGE_ELEMENTS(x) || IS_80211_MESSAGE_ELEMENTS(x))
|
||||
|
||||
#endif /* __CAPWAP_RFC_HEADER__ */
|
||||
#ifndef __CAPWAP_RFC_HEADER__
|
||||
#define __CAPWAP_RFC_HEADER__
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifndef STRUCT_PACKED
|
||||
#define STRUCT_PACKED __attribute__((__packed__))
|
||||
#endif
|
||||
|
||||
#define CAPWAP_PROTOCOL_VERSION 0
|
||||
|
||||
#define CAPWAP_MTU_DEFAULT 1400
|
||||
#define CAPWAP_DONT_FRAGMENT 0
|
||||
|
||||
/* Capwap preamble */
|
||||
#define CAPWAP_PREAMBLE_HEADER 0
|
||||
#define CAPWAP_PREAMBLE_DTLS_HEADER 1
|
||||
|
||||
struct capwap_preamble {
|
||||
#ifdef CAPWAP_BIG_ENDIAN
|
||||
uint8_t version : 4;
|
||||
uint8_t type : 4;
|
||||
#else
|
||||
uint8_t type : 4;
|
||||
uint8_t version : 4;
|
||||
#endif
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Capwap DTLS header */
|
||||
struct capwap_dtls_header {
|
||||
struct capwap_preamble preamble;
|
||||
uint8_t reserved1;
|
||||
uint8_t reserved2;
|
||||
uint8_t reserved3;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Capwap header: 8 (header) + 12 (radio mac) + 256 (wireless info) */
|
||||
#define CAPWAP_HEADER_MAX_SIZE 276
|
||||
struct capwap_header {
|
||||
struct capwap_preamble preamble;
|
||||
#ifdef CAPWAP_BIG_ENDIAN
|
||||
uint16_t hlen : 5;
|
||||
uint16_t rid : 5;
|
||||
uint16_t wbid : 5;
|
||||
uint16_t flag_t : 1;
|
||||
uint8_t flag_f : 1;
|
||||
uint8_t flag_l : 1;
|
||||
uint8_t flag_w : 1;
|
||||
uint8_t flag_m : 1;
|
||||
uint8_t flag_k : 1;
|
||||
uint8_t flag_res : 3;
|
||||
#else
|
||||
uint16_t _rid_hi : 3;
|
||||
uint16_t hlen : 5;
|
||||
uint16_t flag_t : 1;
|
||||
uint16_t wbid : 5;
|
||||
uint16_t _rid_lo : 2;
|
||||
uint8_t flag_res : 3;
|
||||
uint8_t flag_k : 1;
|
||||
uint8_t flag_m : 1;
|
||||
uint8_t flag_w : 1;
|
||||
uint8_t flag_l : 1;
|
||||
uint8_t flag_f : 1;
|
||||
#endif
|
||||
uint16_t frag_id;
|
||||
uint16_t frag_off; /* Only first 13 bit */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define FRAGMENT_OFFSET_MASK 0xfff8
|
||||
|
||||
/* Mac Address */
|
||||
struct capwap_mac_address {
|
||||
uint8_t length;
|
||||
uint8_t address[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Wireless Information */
|
||||
struct capwap_wireless_information {
|
||||
uint8_t length;
|
||||
uint8_t data[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* IEEE802.11 Wireless Information */
|
||||
struct capwap_ieee80211_frame_info {
|
||||
uint8_t rssi;
|
||||
uint8_t snr;
|
||||
uint16_t rate;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Message element */
|
||||
struct capwap_message_element {
|
||||
uint16_t type;
|
||||
uint16_t length;
|
||||
uint8_t data[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Control Message Type */
|
||||
#define CAPWAP_FIRST_MESSAGE_TYPE 1
|
||||
#define CAPWAP_DISCOVERY_REQUEST 1
|
||||
#define CAPWAP_DISCOVERY_RESPONSE 2
|
||||
#define CAPWAP_JOIN_REQUEST 3
|
||||
#define CAPWAP_JOIN_RESPONSE 4
|
||||
#define CAPWAP_CONFIGURATION_STATUS_REQUEST 5
|
||||
#define CAPWAP_CONFIGURATION_STATUS_RESPONSE 6
|
||||
#define CAPWAP_CONFIGURATION_UPDATE_REQUEST 7
|
||||
#define CAPWAP_CONFIGURATION_UPDATE_RESPONSE 8
|
||||
#define CAPWAP_WTP_EVENT_REQUEST 9
|
||||
#define CAPWAP_WTP_EVENT_RESPONSE 10
|
||||
#define CAPWAP_CHANGE_STATE_EVENT_REQUEST 11
|
||||
#define CAPWAP_CHANGE_STATE_EVENT_RESPONSE 12
|
||||
#define CAPWAP_ECHO_REQUEST 13
|
||||
#define CAPWAP_ECHO_RESPONSE 14
|
||||
#define CAPWAP_IMAGE_DATA_REQUEST 15
|
||||
#define CAPWAP_IMAGE_DATA_RESPONSE 16
|
||||
#define CAPWAP_RESET_REQUEST 17
|
||||
#define CAPWAP_RESET_RESPONSE 18
|
||||
#define CAPWAP_PRIMARY_DISCOVERY_REQUEST 19
|
||||
#define CAPWAP_PRIMARY_DISCOVERY_RESPONSE 20
|
||||
#define CAPWAP_DATA_TRANSFER_REQUEST 21
|
||||
#define CAPWAP_DATA_TRANSFER_RESPONSE 22
|
||||
#define CAPWAP_CLEAR_CONFIGURATION_REQUEST 23
|
||||
#define CAPWAP_CLEAR_CONFIGURATION_RESPONSE 24
|
||||
#define CAPWAP_STATION_CONFIGURATION_REQUEST 25
|
||||
#define CAPWAP_STATION_CONFIGURATION_RESPONSE 26
|
||||
#define CAPWAP_LAST_MESSAGE_TYPE 26
|
||||
#define CAPWAP_VALID_MESSAGE_TYPE(x) (((x) >= CAPWAP_FIRST_MESSAGE_TYPE) && ((x) <= CAPWAP_LAST_MESSAGE_TYPE))
|
||||
|
||||
#define CAPWAP_IEEE80211_FIRST_MESSAGE_TYPE 3398913
|
||||
#define CAPWAP_IEEE80211_WLAN_CONFIGURATION_REQUEST 3398913
|
||||
#define CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE 3398914
|
||||
#define CAPWAP_IEEE80211_LAST_MESSAGE_TYPE 3398914
|
||||
#define CAPWAP_VALID_IEEE80211_MESSAGE_TYPE(x) (((x) >= CAPWAP_IEEE80211_FIRST_MESSAGE_TYPE) && ((x) <= CAPWAP_IEEE80211_LAST_MESSAGE_TYPE))
|
||||
|
||||
/* Control Message */
|
||||
#define CAPWAP_CONTROL_MESSAGE_MIN_LENGTH 3
|
||||
|
||||
struct capwap_control_message {
|
||||
uint32_t type;
|
||||
uint8_t seq;
|
||||
uint16_t length;
|
||||
uint8_t flags;
|
||||
uint8_t elements[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Data Message Keep-Alive*/
|
||||
#define CAPWAP_DATA_MESSAGE_KEEPALIVE_MIN_LENGTH 2
|
||||
|
||||
struct capwap_data_message {
|
||||
uint16_t length;
|
||||
uint8_t elements[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Capwap dtls header helper */
|
||||
#define GET_DTLS_BODY(x) (void*)(((uint8_t*)(x)) + sizeof(struct capwap_dtls_header))
|
||||
|
||||
/* Capwap header helper */
|
||||
#define GET_VERSION_HEADER(x) ((x)->preamble.version)
|
||||
#define SET_VERSION_HEADER(x, y) ((x)->preamble.version = (uint8_t)(y))
|
||||
#define GET_TYPE_HEADER(x) ((x)->preamble.type)
|
||||
#define SET_TYPE_HEADER(x, y) ((x)->preamble.type = (uint8_t)(y))
|
||||
|
||||
#define GET_HLEN_HEADER(x) ((x)->hlen)
|
||||
#define SET_HLEN_HEADER(x, y) ((x)->hlen = (uint16_t)(y))
|
||||
#ifdef CAPWAP_BIG_ENDIAN
|
||||
#define GET_RID_HEADER(x) ((uint8_t)((x)->rid))
|
||||
#define SET_RID_HEADER(x, y) ((x)->rid = (uint16_t)(y))
|
||||
#else
|
||||
#define GET_RID_HEADER(x) ((uint8_t)((uint16_t)((x)->_rid_hi << 2 | (x)->_rid_lo)))
|
||||
#define SET_RID_HEADER(x, y) ({ (x)->_rid_hi = (uint16_t)((y) >> 2); (x)->_rid_lo = (uint16_t)((y) & 0x0003); })
|
||||
#endif
|
||||
#define GET_WBID_HEADER(x) ((x)->wbid)
|
||||
#define SET_WBID_HEADER(x, y) ((x)->wbid = (uint16_t)(y))
|
||||
|
||||
#define IS_FLAG_T_HEADER(x) ((x)->flag_t)
|
||||
#define SET_FLAG_T_HEADER(x, y) ((x)->flag_t = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_F_HEADER(x) ((x)->flag_f)
|
||||
#define SET_FLAG_F_HEADER(x, y) ((x)->flag_f = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_L_HEADER(x) ((x)->flag_l)
|
||||
#define SET_FLAG_L_HEADER(x, y) ((x)->flag_l = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_W_HEADER(x) ((x)->flag_w)
|
||||
#define SET_FLAG_W_HEADER(x, y) ((x)->flag_w = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_M_HEADER(x) ((x)->flag_m)
|
||||
#define SET_FLAG_M_HEADER(x, y) ((x)->flag_m = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_K_HEADER(x) ((x)->flag_k)
|
||||
#define SET_FLAG_K_HEADER(x, y) ((x)->flag_k = ((y) ? 1 : 0))
|
||||
|
||||
#define GET_FRAGMENT_ID_HEADER(x) (ntohs((x)->frag_id))
|
||||
#define SET_FRAGMENT_ID_HEADER(x, y) ((x)->frag_id = htons((uint16_t)(y)))
|
||||
#define GET_FRAGMENT_OFFSET_HEADER(x) (ntohs((x)->frag_off) & FRAGMENT_OFFSET_MASK)
|
||||
#define SET_FRAGMENT_OFFSET_HEADER(x, y) ((x)->frag_off &= ~FRAGMENT_OFFSET_MASK, (x)->frag_off |= htons((uint16_t)(y) & FRAGMENT_OFFSET_MASK))
|
||||
|
||||
#define GET_RADIO_MAC_ADDRESS_STRUCT(x) ((struct capwap_mac_address*)(((uint8_t*)(x)) + sizeof(struct capwap_header)))
|
||||
#define GET_WIRELESS_INFORMATION_STRUCT(x) ((struct capwap_wireless_information*)(((uint8_t*)(x)) + sizeof(struct capwap_header) + (IS_FLAG_M_HEADER(x) ? (((GET_RADIO_MAC_ADDRESS_STRUCT(x)->length + sizeof(struct capwap_mac_address)) + 3) / 4) * 4 : 0)))
|
||||
#define GET_PAYLOAD_HEADER(x) ((void*)(((uint8_t*)(x)) + GET_HLEN_HEADER(x) * 4))
|
||||
|
||||
#define IS_SEQUENCE_SMALLER(s1, s2) (((((s1) < (s2)) && (((s2) - (s1)) < 128)) || (((s1) > (s2)) && (((s1) - (s2)) > 128))) ? 1 : 0)
|
||||
|
||||
/* */
|
||||
#define MACADDRESS_NONE_LENGTH 0
|
||||
|
||||
/* */
|
||||
#define MACADDRESS_EUI48_LENGTH 6
|
||||
struct capwap_macaddress_eui48 {
|
||||
uint8_t macaddress[MACADDRESS_EUI48_LENGTH];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* */
|
||||
#define MACADDRESS_EUI64_LENGTH 8
|
||||
struct capwap_macaddress_eui64 {
|
||||
uint8_t macaddress[MACADDRESS_EUI64_LENGTH];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define IS_VALID_MACADDRESS_LENGTH(x) ((x == MACADDRESS_EUI48_LENGTH) || (x == MACADDRESS_EUI64_LENGTH))
|
||||
|
||||
#define RADIOID_MAX_COUNT 31
|
||||
#define IS_VALID_RADIOID(x) ((x >= 1) && (x <= RADIOID_MAX_COUNT))
|
||||
|
||||
#define WLANID_MAX_COUNT 16
|
||||
#define IS_VALID_WLANID(x) ((x >= 1) && (x <= WLANID_MAX_COUNT))
|
||||
|
||||
/* Standard message elements 1 -> 52 (1 - 1023) */
|
||||
#define CAPWAP_MESSAGE_ELEMENTS_START 1
|
||||
#define CAPWAP_MESSAGE_ELEMENTS_STOP 53
|
||||
#define CAPWAP_MESSAGE_ELEMENTS_COUNT ((CAPWAP_MESSAGE_ELEMENTS_STOP - CAPWAP_MESSAGE_ELEMENTS_START) + 1)
|
||||
#define IS_MESSAGE_ELEMENTS(x) (((x >= CAPWAP_MESSAGE_ELEMENTS_START) && (x <= CAPWAP_MESSAGE_ELEMENTS_STOP)) ? 1 : 0)
|
||||
|
||||
/* 802.11 message elements 1024 -> 1024 (1024 - 2047) */
|
||||
#define CAPWAP_80211_MESSAGE_ELEMENTS_START 1024
|
||||
#define CAPWAP_80211_MESSAGE_ELEMENTS_STOP 1048
|
||||
#define CAPWAP_80211_MESSAGE_ELEMENTS_COUNT ((CAPWAP_80211_MESSAGE_ELEMENTS_STOP - CAPWAP_80211_MESSAGE_ELEMENTS_START) + 1)
|
||||
#define IS_80211_MESSAGE_ELEMENTS(x) (((x >= CAPWAP_80211_MESSAGE_ELEMENTS_START) && (x <= CAPWAP_80211_MESSAGE_ELEMENTS_STOP)) ? 1 : 0)
|
||||
|
||||
/* */
|
||||
#define IS_VALID_MESSAGE_ELEMENTS(x) (IS_MESSAGE_ELEMENTS(x) || IS_80211_MESSAGE_ELEMENTS(x))
|
||||
|
||||
#endif /* __CAPWAP_RFC_HEADER__ */
|
||||
|
@ -1,388 +1,388 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_network.h"
|
||||
#include "capwap_socket.h"
|
||||
|
||||
#include <cyassl/options.h>
|
||||
#include <cyassl/ssl.h>
|
||||
|
||||
/* */
|
||||
static int capwap_socket_nonblocking(int sock, int nonblocking) {
|
||||
int flags;
|
||||
|
||||
ASSERT(sock >= 0);
|
||||
|
||||
/* Retrieve file descriptor flags */
|
||||
flags = fcntl(sock, F_GETFL, NULL);
|
||||
if (flags < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nonblocking) {
|
||||
flags |= O_NONBLOCK;
|
||||
} else {
|
||||
flags &= ~O_NONBLOCK;
|
||||
}
|
||||
|
||||
if(fcntl(sock, F_SETFL, flags) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_socket_connect(int sock, union sockaddr_capwap* address, int timeout) {
|
||||
int result;
|
||||
struct pollfd fds;
|
||||
socklen_t size;
|
||||
|
||||
ASSERT(sock >= 0);
|
||||
ASSERT(address != NULL);
|
||||
|
||||
/* Non blocking socket */
|
||||
if (!capwap_socket_nonblocking(sock, 1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
result = connect(sock, &address->sa, sizeof(union sockaddr_capwap));
|
||||
if (result < 0) {
|
||||
if (errno == EINPROGRESS) {
|
||||
/* Wait to connection complete */
|
||||
for (;;) {
|
||||
memset(&fds, 0, sizeof(struct pollfd));
|
||||
fds.fd = sock;
|
||||
fds.events = POLLOUT;
|
||||
|
||||
result = poll(&fds, 1, timeout);
|
||||
if (!result || ((result < 0) && (errno != EINTR))) {
|
||||
return 0;
|
||||
} else if (result > 0) {
|
||||
/* Check connection status */
|
||||
size = sizeof(int);
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&result, &size) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Connection complete */
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Unable to connect to remote host */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int capwap_socket_crypto_verifycertificate(int preverify, CYASSL_X509_STORE_CTX* store) {
|
||||
return preverify;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_socket_crypto_createcontext(char* calist, char* cert, char* privatekey) {
|
||||
CYASSL_CTX* context = NULL;
|
||||
|
||||
ASSERT(calist != NULL);
|
||||
ASSERT(cert != NULL);
|
||||
ASSERT(privatekey != NULL);
|
||||
|
||||
/* Create SSL context */
|
||||
context = CyaSSL_CTX_new(CyaTLSv1_2_client_method());
|
||||
if (context) {
|
||||
/* Public certificate */
|
||||
if (!CyaSSL_CTX_use_certificate_file(context, cert, SSL_FILETYPE_PEM)) {
|
||||
capwap_logging_debug("Error to load certificate file");
|
||||
capwap_socket_crypto_freecontext(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Private key */
|
||||
if (!CyaSSL_CTX_use_PrivateKey_file(context, privatekey, SSL_FILETYPE_PEM)) {
|
||||
capwap_logging_debug("Error to load private key file");
|
||||
capwap_socket_crypto_freecontext(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!CyaSSL_CTX_check_private_key(context)) {
|
||||
capwap_logging_debug("Error to check private key");
|
||||
capwap_socket_crypto_freecontext(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Certificate Authority */
|
||||
if (!CyaSSL_CTX_load_verify_locations(context, calist, NULL)) {
|
||||
capwap_logging_debug("Error to load ca file");
|
||||
capwap_socket_crypto_freecontext(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Verify certificate callback */
|
||||
CyaSSL_CTX_set_verify(context, SSL_VERIFY_PEER, capwap_socket_crypto_verifycertificate);
|
||||
|
||||
/* Set only high security cipher list */
|
||||
if (!CyaSSL_CTX_set_cipher_list(context, "AES256-SHA")) {
|
||||
capwap_logging_debug("Error to select cipher list");
|
||||
capwap_socket_crypto_freecontext(context);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (void*)context;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_socket_crypto_freecontext(void* context) {
|
||||
CYASSL_CTX* sslcontext = (CYASSL_CTX*)context;
|
||||
|
||||
if (sslcontext) {
|
||||
CyaSSL_CTX_free(sslcontext);
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
struct capwap_socket_ssl* capwap_socket_ssl_connect(int sock, void* sslcontext, int timeout) {
|
||||
int result;
|
||||
struct pollfd fds;
|
||||
struct capwap_socket_ssl* sslsock;
|
||||
|
||||
ASSERT(sock >= 0);
|
||||
ASSERT(sslcontext != NULL);
|
||||
|
||||
/* Create SSL session */
|
||||
sslsock = capwap_alloc(sizeof(struct capwap_socket_ssl));
|
||||
sslsock->sock = sock;
|
||||
sslsock->sslcontext = sslcontext;
|
||||
sslsock->sslsession = (void*)CyaSSL_new((CYASSL_CTX*)sslcontext);
|
||||
if (!sslsock->sslsession) {
|
||||
capwap_free(sslsock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set socket to SSL session */
|
||||
if (!CyaSSL_set_fd((CYASSL*)sslsock->sslsession, sock)) {
|
||||
CyaSSL_free((CYASSL*)sslsock->sslsession);
|
||||
capwap_free(sslsock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
CyaSSL_set_using_nonblock((CYASSL*)sslsock->sslsession, 1);
|
||||
|
||||
/* Establish SSL connection */
|
||||
for (;;) {
|
||||
result = CyaSSL_connect((CYASSL*)sslsock->sslsession);
|
||||
if (result == SSL_SUCCESS) {
|
||||
break; /* Connection complete */
|
||||
} else {
|
||||
int error = CyaSSL_get_error((CYASSL*)sslsock->sslsession, 0);
|
||||
if ((error == SSL_ERROR_WANT_READ) || (error == SSL_ERROR_WANT_WRITE)) {
|
||||
memset(&fds, 0, sizeof(struct pollfd));
|
||||
fds.fd = sock;
|
||||
fds.events = ((error == SSL_ERROR_WANT_READ) ? POLLIN : POLLOUT);
|
||||
|
||||
result = poll(&fds, 1, timeout);
|
||||
if (((result < 0) && (errno != EINTR)) || ((result > 0) && (fds.events != fds.revents))) {
|
||||
CyaSSL_free((CYASSL*)sslsock->sslsession);
|
||||
capwap_free(sslsock);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
CyaSSL_free((CYASSL*)sslsock->sslsession);
|
||||
capwap_free(sslsock);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sslsock;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_socket_crypto_send(struct capwap_socket_ssl* sslsock, void* buffer, size_t length, int timeout) {
|
||||
int result;
|
||||
|
||||
ASSERT(sslsock != NULL);
|
||||
ASSERT(sslsock->sslsession != NULL);
|
||||
ASSERT(sslsock->sock >= 0);
|
||||
ASSERT(buffer != NULL);
|
||||
ASSERT(length > 0);
|
||||
|
||||
result = CyaSSL_write((CYASSL*)sslsock->sslsession, buffer, length);
|
||||
if (result != length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_socket_crypto_recv(struct capwap_socket_ssl* sslsock, void* buffer, size_t length, int timeout) {
|
||||
int result;
|
||||
struct pollfd fds;
|
||||
|
||||
ASSERT(sslsock != NULL);
|
||||
ASSERT(sslsock->sslsession != NULL);
|
||||
ASSERT(sslsock->sock >= 0);
|
||||
ASSERT(buffer != NULL);
|
||||
ASSERT(length > 0);
|
||||
|
||||
for (;;) {
|
||||
result = CyaSSL_read((CYASSL*)sslsock->sslsession, buffer, length);
|
||||
if (result >= 0) {
|
||||
return result;
|
||||
} else {
|
||||
int error = CyaSSL_get_error((CYASSL*)sslsock->sslsession, 0);
|
||||
if ((error == SSL_ERROR_WANT_READ) || (error == SSL_ERROR_WANT_WRITE)) {
|
||||
memset(&fds, 0, sizeof(struct pollfd));
|
||||
fds.fd = sslsock->sock;
|
||||
fds.events = ((error == SSL_ERROR_WANT_READ) ? POLLIN : POLLOUT);
|
||||
|
||||
result = poll(&fds, 1, timeout);
|
||||
if (((result < 0) && (errno != EINTR)) || ((result > 0) && (fds.events != fds.revents))) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_socket_ssl_shutdown(struct capwap_socket_ssl* sslsock, int timeout) {
|
||||
int result;
|
||||
struct pollfd fds;
|
||||
|
||||
ASSERT(sslsock != NULL);
|
||||
ASSERT(sslsock->sslsession != NULL);
|
||||
ASSERT(sslsock->sock >= 0);
|
||||
|
||||
/* */
|
||||
for (;;) {
|
||||
result = CyaSSL_shutdown((CYASSL*)sslsock->sslsession);
|
||||
if (result >= 0) {
|
||||
break; /* Shutdown complete */
|
||||
} else {
|
||||
int error = CyaSSL_get_error((CYASSL*)sslsock->sslsession, 0);
|
||||
if ((error == SSL_ERROR_WANT_READ) || (error == SSL_ERROR_WANT_WRITE)) {
|
||||
memset(&fds, 0, sizeof(struct pollfd));
|
||||
fds.fd = sslsock->sock;
|
||||
fds.events = ((error == SSL_ERROR_WANT_READ) ? POLLIN : POLLOUT);
|
||||
|
||||
result = poll(&fds, 1, timeout);
|
||||
if (((result < 0) && (errno != EINTR)) || ((result > 0) && (fds.events != fds.revents))) {
|
||||
break; /* Shutdown error */
|
||||
}
|
||||
} else {
|
||||
break; /* Shutdown error */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_socket_ssl_close(struct capwap_socket_ssl* sslsock) {
|
||||
ASSERT(sslsock != NULL);
|
||||
ASSERT(sslsock->sslsession != NULL);
|
||||
|
||||
CyaSSL_free((CYASSL*)sslsock->sslsession);
|
||||
sslsock->sslsession = NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_socket_shutdown(int sock) {
|
||||
ASSERT(sock >= 0);
|
||||
|
||||
shutdown(sock, SHUT_RDWR);
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_socket_close(int sock) {
|
||||
ASSERT(sock >= 0);
|
||||
|
||||
capwap_socket_shutdown(sock);
|
||||
capwap_socket_nonblocking(sock, 0);
|
||||
close(sock);
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_socket_send(int sock, void* buffer, size_t length, int timeout) {
|
||||
int result;
|
||||
struct pollfd fds;
|
||||
size_t sendlength;
|
||||
|
||||
ASSERT(sock >= 0);
|
||||
ASSERT(buffer != NULL);
|
||||
ASSERT(length > 0);
|
||||
|
||||
sendlength = 0;
|
||||
while (sendlength < length) {
|
||||
memset(&fds, 0, sizeof(struct pollfd));
|
||||
fds.fd = sock;
|
||||
fds.events = POLLOUT;
|
||||
|
||||
result = poll(&fds, 1, timeout);
|
||||
if ((result < 0) && (errno != EINTR)) {
|
||||
return -1;
|
||||
} else if (result > 0) {
|
||||
if (fds.revents == POLLOUT) {
|
||||
size_t leftlength = length - sendlength;
|
||||
|
||||
result = send(sock, &((char*)buffer)[sendlength], leftlength, 0);
|
||||
if ((result < 0) && (errno != EINTR)) {
|
||||
return -1;
|
||||
} else if (result > 0) {
|
||||
sendlength += result;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sendlength;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_socket_recv(int sock, void* buffer, size_t length, int timeout) {
|
||||
int result;
|
||||
struct pollfd fds;
|
||||
|
||||
ASSERT(sock >= 0);
|
||||
ASSERT(buffer != NULL);
|
||||
ASSERT(length > 0);
|
||||
|
||||
for (;;) {
|
||||
memset(&fds, 0, sizeof(struct pollfd));
|
||||
fds.fd = sock;
|
||||
fds.events = POLLIN;
|
||||
|
||||
result = poll(&fds, 1, timeout);
|
||||
if ((result < 0) && (errno != EINTR)) {
|
||||
break;
|
||||
} else if (result > 0) {
|
||||
if (fds.revents == POLLIN) {
|
||||
result = recv(sock, buffer, length, 0);
|
||||
if ((result < 0) && (errno != EINTR)) {
|
||||
break;
|
||||
} else if (result >= 0) {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#include "capwap.h"
|
||||
#include "capwap_network.h"
|
||||
#include "capwap_socket.h"
|
||||
|
||||
#include <cyassl/options.h>
|
||||
#include <cyassl/ssl.h>
|
||||
|
||||
/* */
|
||||
static int capwap_socket_nonblocking(int sock, int nonblocking) {
|
||||
int flags;
|
||||
|
||||
ASSERT(sock >= 0);
|
||||
|
||||
/* Retrieve file descriptor flags */
|
||||
flags = fcntl(sock, F_GETFL, NULL);
|
||||
if (flags < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nonblocking) {
|
||||
flags |= O_NONBLOCK;
|
||||
} else {
|
||||
flags &= ~O_NONBLOCK;
|
||||
}
|
||||
|
||||
if(fcntl(sock, F_SETFL, flags) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_socket_connect(int sock, union sockaddr_capwap* address, int timeout) {
|
||||
int result;
|
||||
struct pollfd fds;
|
||||
socklen_t size;
|
||||
|
||||
ASSERT(sock >= 0);
|
||||
ASSERT(address != NULL);
|
||||
|
||||
/* Non blocking socket */
|
||||
if (!capwap_socket_nonblocking(sock, 1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
result = connect(sock, &address->sa, sizeof(union sockaddr_capwap));
|
||||
if (result < 0) {
|
||||
if (errno == EINPROGRESS) {
|
||||
/* Wait to connection complete */
|
||||
for (;;) {
|
||||
memset(&fds, 0, sizeof(struct pollfd));
|
||||
fds.fd = sock;
|
||||
fds.events = POLLOUT;
|
||||
|
||||
result = poll(&fds, 1, timeout);
|
||||
if (!result || ((result < 0) && (errno != EINTR))) {
|
||||
return 0;
|
||||
} else if (result > 0) {
|
||||
/* Check connection status */
|
||||
size = sizeof(int);
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&result, &size) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Connection complete */
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Unable to connect to remote host */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int capwap_socket_crypto_verifycertificate(int preverify, CYASSL_X509_STORE_CTX* store) {
|
||||
return preverify;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_socket_crypto_createcontext(char* calist, char* cert, char* privatekey) {
|
||||
CYASSL_CTX* context = NULL;
|
||||
|
||||
ASSERT(calist != NULL);
|
||||
ASSERT(cert != NULL);
|
||||
ASSERT(privatekey != NULL);
|
||||
|
||||
/* Create SSL context */
|
||||
context = CyaSSL_CTX_new(CyaTLSv1_2_client_method());
|
||||
if (context) {
|
||||
/* Public certificate */
|
||||
if (!CyaSSL_CTX_use_certificate_file(context, cert, SSL_FILETYPE_PEM)) {
|
||||
capwap_logging_debug("Error to load certificate file");
|
||||
capwap_socket_crypto_freecontext(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Private key */
|
||||
if (!CyaSSL_CTX_use_PrivateKey_file(context, privatekey, SSL_FILETYPE_PEM)) {
|
||||
capwap_logging_debug("Error to load private key file");
|
||||
capwap_socket_crypto_freecontext(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!CyaSSL_CTX_check_private_key(context)) {
|
||||
capwap_logging_debug("Error to check private key");
|
||||
capwap_socket_crypto_freecontext(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Certificate Authority */
|
||||
if (!CyaSSL_CTX_load_verify_locations(context, calist, NULL)) {
|
||||
capwap_logging_debug("Error to load ca file");
|
||||
capwap_socket_crypto_freecontext(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Verify certificate callback */
|
||||
CyaSSL_CTX_set_verify(context, SSL_VERIFY_PEER, capwap_socket_crypto_verifycertificate);
|
||||
|
||||
/* Set only high security cipher list */
|
||||
if (!CyaSSL_CTX_set_cipher_list(context, "AES256-SHA")) {
|
||||
capwap_logging_debug("Error to select cipher list");
|
||||
capwap_socket_crypto_freecontext(context);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (void*)context;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_socket_crypto_freecontext(void* context) {
|
||||
CYASSL_CTX* sslcontext = (CYASSL_CTX*)context;
|
||||
|
||||
if (sslcontext) {
|
||||
CyaSSL_CTX_free(sslcontext);
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
struct capwap_socket_ssl* capwap_socket_ssl_connect(int sock, void* sslcontext, int timeout) {
|
||||
int result;
|
||||
struct pollfd fds;
|
||||
struct capwap_socket_ssl* sslsock;
|
||||
|
||||
ASSERT(sock >= 0);
|
||||
ASSERT(sslcontext != NULL);
|
||||
|
||||
/* Create SSL session */
|
||||
sslsock = capwap_alloc(sizeof(struct capwap_socket_ssl));
|
||||
sslsock->sock = sock;
|
||||
sslsock->sslcontext = sslcontext;
|
||||
sslsock->sslsession = (void*)CyaSSL_new((CYASSL_CTX*)sslcontext);
|
||||
if (!sslsock->sslsession) {
|
||||
capwap_free(sslsock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set socket to SSL session */
|
||||
if (!CyaSSL_set_fd((CYASSL*)sslsock->sslsession, sock)) {
|
||||
CyaSSL_free((CYASSL*)sslsock->sslsession);
|
||||
capwap_free(sslsock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
CyaSSL_set_using_nonblock((CYASSL*)sslsock->sslsession, 1);
|
||||
|
||||
/* Establish SSL connection */
|
||||
for (;;) {
|
||||
result = CyaSSL_connect((CYASSL*)sslsock->sslsession);
|
||||
if (result == SSL_SUCCESS) {
|
||||
break; /* Connection complete */
|
||||
} else {
|
||||
int error = CyaSSL_get_error((CYASSL*)sslsock->sslsession, 0);
|
||||
if ((error == SSL_ERROR_WANT_READ) || (error == SSL_ERROR_WANT_WRITE)) {
|
||||
memset(&fds, 0, sizeof(struct pollfd));
|
||||
fds.fd = sock;
|
||||
fds.events = ((error == SSL_ERROR_WANT_READ) ? POLLIN : POLLOUT);
|
||||
|
||||
result = poll(&fds, 1, timeout);
|
||||
if (((result < 0) && (errno != EINTR)) || ((result > 0) && (fds.events != fds.revents))) {
|
||||
CyaSSL_free((CYASSL*)sslsock->sslsession);
|
||||
capwap_free(sslsock);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
CyaSSL_free((CYASSL*)sslsock->sslsession);
|
||||
capwap_free(sslsock);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sslsock;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_socket_crypto_send(struct capwap_socket_ssl* sslsock, void* buffer, size_t length, int timeout) {
|
||||
int result;
|
||||
|
||||
ASSERT(sslsock != NULL);
|
||||
ASSERT(sslsock->sslsession != NULL);
|
||||
ASSERT(sslsock->sock >= 0);
|
||||
ASSERT(buffer != NULL);
|
||||
ASSERT(length > 0);
|
||||
|
||||
result = CyaSSL_write((CYASSL*)sslsock->sslsession, buffer, length);
|
||||
if (result != length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_socket_crypto_recv(struct capwap_socket_ssl* sslsock, void* buffer, size_t length, int timeout) {
|
||||
int result;
|
||||
struct pollfd fds;
|
||||
|
||||
ASSERT(sslsock != NULL);
|
||||
ASSERT(sslsock->sslsession != NULL);
|
||||
ASSERT(sslsock->sock >= 0);
|
||||
ASSERT(buffer != NULL);
|
||||
ASSERT(length > 0);
|
||||
|
||||
for (;;) {
|
||||
result = CyaSSL_read((CYASSL*)sslsock->sslsession, buffer, length);
|
||||
if (result >= 0) {
|
||||
return result;
|
||||
} else {
|
||||
int error = CyaSSL_get_error((CYASSL*)sslsock->sslsession, 0);
|
||||
if ((error == SSL_ERROR_WANT_READ) || (error == SSL_ERROR_WANT_WRITE)) {
|
||||
memset(&fds, 0, sizeof(struct pollfd));
|
||||
fds.fd = sslsock->sock;
|
||||
fds.events = ((error == SSL_ERROR_WANT_READ) ? POLLIN : POLLOUT);
|
||||
|
||||
result = poll(&fds, 1, timeout);
|
||||
if (((result < 0) && (errno != EINTR)) || ((result > 0) && (fds.events != fds.revents))) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_socket_ssl_shutdown(struct capwap_socket_ssl* sslsock, int timeout) {
|
||||
int result;
|
||||
struct pollfd fds;
|
||||
|
||||
ASSERT(sslsock != NULL);
|
||||
ASSERT(sslsock->sslsession != NULL);
|
||||
ASSERT(sslsock->sock >= 0);
|
||||
|
||||
/* */
|
||||
for (;;) {
|
||||
result = CyaSSL_shutdown((CYASSL*)sslsock->sslsession);
|
||||
if (result >= 0) {
|
||||
break; /* Shutdown complete */
|
||||
} else {
|
||||
int error = CyaSSL_get_error((CYASSL*)sslsock->sslsession, 0);
|
||||
if ((error == SSL_ERROR_WANT_READ) || (error == SSL_ERROR_WANT_WRITE)) {
|
||||
memset(&fds, 0, sizeof(struct pollfd));
|
||||
fds.fd = sslsock->sock;
|
||||
fds.events = ((error == SSL_ERROR_WANT_READ) ? POLLIN : POLLOUT);
|
||||
|
||||
result = poll(&fds, 1, timeout);
|
||||
if (((result < 0) && (errno != EINTR)) || ((result > 0) && (fds.events != fds.revents))) {
|
||||
break; /* Shutdown error */
|
||||
}
|
||||
} else {
|
||||
break; /* Shutdown error */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_socket_ssl_close(struct capwap_socket_ssl* sslsock) {
|
||||
ASSERT(sslsock != NULL);
|
||||
ASSERT(sslsock->sslsession != NULL);
|
||||
|
||||
CyaSSL_free((CYASSL*)sslsock->sslsession);
|
||||
sslsock->sslsession = NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_socket_shutdown(int sock) {
|
||||
ASSERT(sock >= 0);
|
||||
|
||||
shutdown(sock, SHUT_RDWR);
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_socket_close(int sock) {
|
||||
ASSERT(sock >= 0);
|
||||
|
||||
capwap_socket_shutdown(sock);
|
||||
capwap_socket_nonblocking(sock, 0);
|
||||
close(sock);
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_socket_send(int sock, void* buffer, size_t length, int timeout) {
|
||||
int result;
|
||||
struct pollfd fds;
|
||||
size_t sendlength;
|
||||
|
||||
ASSERT(sock >= 0);
|
||||
ASSERT(buffer != NULL);
|
||||
ASSERT(length > 0);
|
||||
|
||||
sendlength = 0;
|
||||
while (sendlength < length) {
|
||||
memset(&fds, 0, sizeof(struct pollfd));
|
||||
fds.fd = sock;
|
||||
fds.events = POLLOUT;
|
||||
|
||||
result = poll(&fds, 1, timeout);
|
||||
if ((result < 0) && (errno != EINTR)) {
|
||||
return -1;
|
||||
} else if (result > 0) {
|
||||
if (fds.revents == POLLOUT) {
|
||||
size_t leftlength = length - sendlength;
|
||||
|
||||
result = send(sock, &((char*)buffer)[sendlength], leftlength, 0);
|
||||
if ((result < 0) && (errno != EINTR)) {
|
||||
return -1;
|
||||
} else if (result > 0) {
|
||||
sendlength += result;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sendlength;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_socket_recv(int sock, void* buffer, size_t length, int timeout) {
|
||||
int result;
|
||||
struct pollfd fds;
|
||||
|
||||
ASSERT(sock >= 0);
|
||||
ASSERT(buffer != NULL);
|
||||
ASSERT(length > 0);
|
||||
|
||||
for (;;) {
|
||||
memset(&fds, 0, sizeof(struct pollfd));
|
||||
fds.fd = sock;
|
||||
fds.events = POLLIN;
|
||||
|
||||
result = poll(&fds, 1, timeout);
|
||||
if ((result < 0) && (errno != EINTR)) {
|
||||
break;
|
||||
} else if (result > 0) {
|
||||
if (fds.revents == POLLIN) {
|
||||
result = recv(sock, buffer, length, 0);
|
||||
if ((result < 0) && (errno != EINTR)) {
|
||||
break;
|
||||
} else if (result >= 0) {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -1,30 +1,30 @@
|
||||
#ifndef __CAPWAP_SOCKET_HEADER__
|
||||
#define __CAPWAP_SOCKET_HEADER__
|
||||
|
||||
/* */
|
||||
int capwap_socket_connect(int sock, union sockaddr_capwap* address, int timeout);
|
||||
void capwap_socket_shutdown(int sock);
|
||||
void capwap_socket_close(int sock);
|
||||
|
||||
/* Plain send/recv */
|
||||
int capwap_socket_send(int sock, void* buffer, size_t length, int timeout);
|
||||
int capwap_socket_recv(int sock, void* buffer, size_t length, int timeout);
|
||||
|
||||
/* SSL send/recv */
|
||||
struct capwap_socket_ssl {
|
||||
int sock;
|
||||
void* sslcontext;
|
||||
void* sslsession;
|
||||
};
|
||||
|
||||
void* capwap_socket_crypto_createcontext(char* calist, char* cert, char* privatekey);
|
||||
void capwap_socket_crypto_freecontext(void* context);
|
||||
|
||||
int capwap_socket_crypto_send(struct capwap_socket_ssl* sslsock, void* buffer, size_t length, int timeout);
|
||||
int capwap_socket_crypto_recv(struct capwap_socket_ssl* sslsock, void* buffer, size_t length, int timeout);
|
||||
|
||||
struct capwap_socket_ssl* capwap_socket_ssl_connect(int sock, void* sslcontext, int timeout);
|
||||
void capwap_socket_ssl_shutdown(struct capwap_socket_ssl* sslsock, int timeout);
|
||||
void capwap_socket_ssl_close(struct capwap_socket_ssl* sslsock);
|
||||
|
||||
#endif /* __CAPWAP_SOCKET_HEADER__ */
|
||||
#ifndef __CAPWAP_SOCKET_HEADER__
|
||||
#define __CAPWAP_SOCKET_HEADER__
|
||||
|
||||
/* */
|
||||
int capwap_socket_connect(int sock, union sockaddr_capwap* address, int timeout);
|
||||
void capwap_socket_shutdown(int sock);
|
||||
void capwap_socket_close(int sock);
|
||||
|
||||
/* Plain send/recv */
|
||||
int capwap_socket_send(int sock, void* buffer, size_t length, int timeout);
|
||||
int capwap_socket_recv(int sock, void* buffer, size_t length, int timeout);
|
||||
|
||||
/* SSL send/recv */
|
||||
struct capwap_socket_ssl {
|
||||
int sock;
|
||||
void* sslcontext;
|
||||
void* sslsession;
|
||||
};
|
||||
|
||||
void* capwap_socket_crypto_createcontext(char* calist, char* cert, char* privatekey);
|
||||
void capwap_socket_crypto_freecontext(void* context);
|
||||
|
||||
int capwap_socket_crypto_send(struct capwap_socket_ssl* sslsock, void* buffer, size_t length, int timeout);
|
||||
int capwap_socket_crypto_recv(struct capwap_socket_ssl* sslsock, void* buffer, size_t length, int timeout);
|
||||
|
||||
struct capwap_socket_ssl* capwap_socket_ssl_connect(int sock, void* sslcontext, int timeout);
|
||||
void capwap_socket_ssl_shutdown(struct capwap_socket_ssl* sslsock, int timeout);
|
||||
void capwap_socket_ssl_close(struct capwap_socket_ssl* sslsock);
|
||||
|
||||
#endif /* __CAPWAP_SOCKET_HEADER__ */
|
||||
|
@ -1,342 +1,342 @@
|
||||
#include "capwap.h"
|
||||
|
||||
/* */
|
||||
#define CAPWAP_TIMEOUT_HASH_COUNT 128
|
||||
|
||||
/* */
|
||||
/* #define CAPWAP_TIMEOUT_LOGGING_DEBUG 1 */
|
||||
|
||||
/* */
|
||||
static unsigned long capwap_timeout_hash_item_gethash(const void* key, unsigned long hashsize) {
|
||||
return (*((unsigned long*)key) % hashsize);
|
||||
}
|
||||
|
||||
/* */
|
||||
static const void* capwap_timeout_hash_item_getkey(const void* data) {
|
||||
return (const void*)&((struct capwap_timeout_item*)((struct capwap_list_item*)data)->item)->index;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int capwap_timeout_hash_item_cmp(const void* key1, const void* key2) {
|
||||
unsigned long value1 = *(unsigned long*)key1;
|
||||
unsigned long value2 = *(unsigned long*)key2;
|
||||
|
||||
return ((value1 == value2) ? 0 : ((value1 < value2) ? -1 : 1));
|
||||
}
|
||||
|
||||
/* */
|
||||
static long capwap_timeout_getdelta(struct timeval* time1, struct timeval* time2) {
|
||||
return (time1->tv_sec - time2->tv_sec) * 1000 + (time1->tv_usec - time2->tv_usec) / 1000;
|
||||
}
|
||||
|
||||
/* */
|
||||
static unsigned long capwap_timeout_set_bitfield(struct capwap_timeout* timeout) {
|
||||
int i, j;
|
||||
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
/* Search free bitfield */
|
||||
for (i = 0; i < CAPWAP_TIMEOUT_BITFIELD_SIZE; i++) {
|
||||
if (timeout->timeoutbitfield[i] != 0xffffffff) {
|
||||
uint32_t bitfield = timeout->timeoutbitfield[i];
|
||||
|
||||
for (j = 0; j < 32; j++) {
|
||||
if (!(bitfield & (1 << j))) {
|
||||
timeout->timeoutbitfield[i] |= (1 << j);
|
||||
return (i * 32 + j + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CAPWAP_TIMEOUT_INDEX_NO_SET;
|
||||
}
|
||||
|
||||
/* */
|
||||
static void capwap_timeout_clear_bitfield(struct capwap_timeout* timeout, unsigned long value) {
|
||||
ASSERT(timeout != NULL);
|
||||
ASSERT(value > 0);
|
||||
|
||||
timeout->timeoutbitfield[(value - 1) / 32] &= ~(1 << ((value - 1) % 32));
|
||||
}
|
||||
|
||||
/* */
|
||||
static void capwap_timeout_additem(struct capwap_list* itemstimeout, struct capwap_list_item* itemlist) {
|
||||
struct capwap_list_item* search;
|
||||
struct capwap_list_item* last = NULL;
|
||||
struct capwap_timeout_item* item = (struct capwap_timeout_item*)itemlist->item;
|
||||
|
||||
/* */
|
||||
search = itemstimeout->first;
|
||||
while (search) {
|
||||
struct capwap_timeout_item* itemsearch = (struct capwap_timeout_item*)search->item;
|
||||
|
||||
if (capwap_timeout_getdelta(&item->expire, &itemsearch->expire) < 0) {
|
||||
capwap_itemlist_insert_before(itemstimeout, last, itemlist);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Next */
|
||||
last = search;
|
||||
search = search->next;
|
||||
}
|
||||
|
||||
/* */
|
||||
if (!search) {
|
||||
capwap_itemlist_insert_after(itemstimeout, NULL, itemlist);
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
static void capwap_timeout_setexpire(long durate, struct timeval* now, struct timeval* expire) {
|
||||
expire->tv_sec = now->tv_sec + durate / 1000;
|
||||
expire->tv_usec = now->tv_usec + durate % 1000;
|
||||
if (expire->tv_usec >= 1000000) {
|
||||
expire->tv_sec++;
|
||||
expire->tv_usec -= 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
struct capwap_timeout* capwap_timeout_init(void) {
|
||||
struct capwap_timeout* timeout;
|
||||
|
||||
/* */
|
||||
timeout = (struct capwap_timeout*)capwap_alloc(sizeof(struct capwap_timeout));
|
||||
memset(timeout, 0, sizeof(struct capwap_timeout));
|
||||
|
||||
/* */
|
||||
timeout->itemsreference = capwap_hash_create(CAPWAP_TIMEOUT_HASH_COUNT);
|
||||
timeout->itemsreference->item_gethash = capwap_timeout_hash_item_gethash;
|
||||
timeout->itemsreference->item_getkey = capwap_timeout_hash_item_getkey;
|
||||
timeout->itemsreference->item_cmp = capwap_timeout_hash_item_cmp;
|
||||
|
||||
timeout->itemstimeout = capwap_list_create();
|
||||
|
||||
return timeout;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_timeout_free(struct capwap_timeout* timeout) {
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
capwap_hash_free(timeout->itemsreference);
|
||||
capwap_list_free(timeout->itemstimeout);
|
||||
capwap_free(timeout);
|
||||
}
|
||||
|
||||
/* */
|
||||
unsigned long capwap_timeout_createtimer(struct capwap_timeout* timeout) {
|
||||
unsigned long index;
|
||||
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
/* Create new timeout index */
|
||||
index = capwap_timeout_set_bitfield(timeout);
|
||||
|
||||
#ifdef CAPWAP_TIMEOUT_LOGGING_DEBUG
|
||||
capwap_logging_debug("Create new timer: %lu", index);
|
||||
#endif
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_timeout_deletetimer(struct capwap_timeout* timeout, unsigned long index) {
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
if (index != CAPWAP_TIMEOUT_INDEX_NO_SET) {
|
||||
#ifdef CAPWAP_TIMEOUT_LOGGING_DEBUG
|
||||
capwap_logging_debug("Delete timer: %lu", index);
|
||||
#endif
|
||||
|
||||
/* Unset timeout timer */
|
||||
capwap_timeout_unset(timeout, index);
|
||||
|
||||
/* Release timer index */
|
||||
capwap_timeout_clear_bitfield(timeout, index);
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
unsigned long capwap_timeout_set(struct capwap_timeout* timeout, unsigned long index, long durate, capwap_timeout_expire callback, void* context, void* param) {
|
||||
struct capwap_list_item* itemlist;
|
||||
struct capwap_timeout_item* item;
|
||||
struct timeval now;
|
||||
|
||||
ASSERT(timeout != NULL);
|
||||
ASSERT(durate >= 0);
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
if (index == CAPWAP_TIMEOUT_INDEX_NO_SET) {
|
||||
index = capwap_timeout_createtimer(timeout);
|
||||
} else {
|
||||
/* Check can update timeout timer */
|
||||
itemlist = (struct capwap_list_item*)capwap_hash_search(timeout->itemsreference, &index);
|
||||
if (itemlist) {
|
||||
/* Remove from timeout list */
|
||||
capwap_itemlist_remove(timeout->itemstimeout, itemlist);
|
||||
|
||||
/* Update timeout */
|
||||
item = (struct capwap_timeout_item*)itemlist->item;
|
||||
item->durate = durate;
|
||||
capwap_timeout_setexpire(item->durate, &now, &item->expire);
|
||||
item->callback = callback;
|
||||
item->context = context;
|
||||
item->param = param;
|
||||
|
||||
#ifdef CAPWAP_TIMEOUT_LOGGING_DEBUG
|
||||
capwap_logging_debug("Update timeout: %lu %ld", item->index, item->durate);
|
||||
#endif
|
||||
|
||||
/* Add itemlist into order list */
|
||||
capwap_timeout_additem(timeout->itemstimeout, itemlist);
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create new timeout timer */
|
||||
itemlist = capwap_itemlist_create(sizeof(struct capwap_timeout_item));
|
||||
item = (struct capwap_timeout_item*)itemlist->item;
|
||||
|
||||
/* */
|
||||
item->index = index;
|
||||
item->durate = durate;
|
||||
capwap_timeout_setexpire(item->durate, &now, &item->expire);
|
||||
item->callback = callback;
|
||||
item->context = context;
|
||||
item->param = param;
|
||||
|
||||
#ifdef CAPWAP_TIMEOUT_LOGGING_DEBUG
|
||||
capwap_logging_debug("Set timeout: %lu %ld", item->index, item->durate);
|
||||
#endif
|
||||
|
||||
/* Add itemlist into hash for rapid searching */
|
||||
capwap_hash_add(timeout->itemsreference, (void*)itemlist);
|
||||
|
||||
/* Add itemlist into order list */
|
||||
capwap_timeout_additem(timeout->itemstimeout, itemlist);
|
||||
|
||||
return item->index;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_timeout_unset(struct capwap_timeout* timeout, unsigned long index) {
|
||||
struct capwap_list_item* itemlist;
|
||||
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
if (index != CAPWAP_TIMEOUT_INDEX_NO_SET) {
|
||||
itemlist = (struct capwap_list_item*)capwap_hash_search(timeout->itemsreference, &index);
|
||||
if (itemlist) {
|
||||
#ifdef CAPWAP_TIMEOUT_LOGGING_DEBUG
|
||||
capwap_logging_debug("Unset timeout: %lu", index);
|
||||
#endif
|
||||
|
||||
/* */
|
||||
capwap_hash_delete(timeout->itemsreference, &index);
|
||||
capwap_itemlist_free(capwap_itemlist_remove(timeout->itemstimeout, itemlist));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_timeout_unsetall(struct capwap_timeout* timeout) {
|
||||
capwap_hash_deleteall(timeout->itemsreference);
|
||||
capwap_list_flush(timeout->itemstimeout);
|
||||
}
|
||||
|
||||
/* */
|
||||
long capwap_timeout_getcoming(struct capwap_timeout* timeout) {
|
||||
long delta;
|
||||
struct timeval now;
|
||||
struct capwap_list_item* search;
|
||||
struct capwap_timeout_item* item;
|
||||
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
/* */
|
||||
search = timeout->itemstimeout->first;
|
||||
if (!search) {
|
||||
return CAPWAP_TIMEOUT_INFINITE;
|
||||
}
|
||||
|
||||
/* */
|
||||
gettimeofday(&now, NULL);
|
||||
item = (struct capwap_timeout_item*)search->item;
|
||||
delta = capwap_timeout_getdelta(&item->expire, &now);
|
||||
|
||||
if (delta <= 0) {
|
||||
return 0;
|
||||
} else if (delta <= item->durate) {
|
||||
return delta;
|
||||
}
|
||||
|
||||
/* Recalculate all timeouts because delta > item->durate */
|
||||
while (search) {
|
||||
struct capwap_timeout_item* itemsearch = (struct capwap_timeout_item*)search->item;
|
||||
|
||||
capwap_timeout_setexpire(itemsearch->durate, &now, &itemsearch->expire);
|
||||
search = search->next;
|
||||
}
|
||||
|
||||
return item->durate;
|
||||
}
|
||||
|
||||
/* */
|
||||
unsigned long capwap_timeout_hasexpired(struct capwap_timeout* timeout) {
|
||||
long delta;
|
||||
struct capwap_timeout_item* item;
|
||||
struct capwap_list_item* itemlist;
|
||||
unsigned long index;
|
||||
capwap_timeout_expire callback;
|
||||
void* context;
|
||||
void* param;
|
||||
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
/* */
|
||||
delta = capwap_timeout_getcoming(timeout);
|
||||
if ((delta > 0) || (delta == CAPWAP_TIMEOUT_INFINITE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
itemlist = capwap_itemlist_remove_head(timeout->itemstimeout);
|
||||
item = (struct capwap_timeout_item*)itemlist->item;
|
||||
|
||||
#ifdef CAPWAP_TIMEOUT_LOGGING_DEBUG
|
||||
capwap_logging_debug("Expired timeout: %lu", item->index);
|
||||
#endif
|
||||
|
||||
/* Cache callback before release timeout timer */
|
||||
index = item->index;
|
||||
callback = item->callback;
|
||||
context = item->context;
|
||||
param = item->param;
|
||||
|
||||
/* Free memory */
|
||||
capwap_hash_delete(timeout->itemsreference, &index);
|
||||
capwap_itemlist_free(itemlist);
|
||||
|
||||
/* */
|
||||
if (callback) {
|
||||
callback(timeout, index, context, param);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_timeout_wait(long durate) {
|
||||
if (durate < 0) {
|
||||
return -1;
|
||||
} else if (durate > 0) {
|
||||
if (usleep((useconds_t)durate * 1000)) {
|
||||
return ((errno == EINTR) ? 0 : -1);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#include "capwap.h"
|
||||
|
||||
/* */
|
||||
#define CAPWAP_TIMEOUT_HASH_COUNT 128
|
||||
|
||||
/* */
|
||||
/* #define CAPWAP_TIMEOUT_LOGGING_DEBUG 1 */
|
||||
|
||||
/* */
|
||||
static unsigned long capwap_timeout_hash_item_gethash(const void* key, unsigned long hashsize) {
|
||||
return (*((unsigned long*)key) % hashsize);
|
||||
}
|
||||
|
||||
/* */
|
||||
static const void* capwap_timeout_hash_item_getkey(const void* data) {
|
||||
return (const void*)&((struct capwap_timeout_item*)((struct capwap_list_item*)data)->item)->index;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int capwap_timeout_hash_item_cmp(const void* key1, const void* key2) {
|
||||
unsigned long value1 = *(unsigned long*)key1;
|
||||
unsigned long value2 = *(unsigned long*)key2;
|
||||
|
||||
return ((value1 == value2) ? 0 : ((value1 < value2) ? -1 : 1));
|
||||
}
|
||||
|
||||
/* */
|
||||
static long capwap_timeout_getdelta(struct timeval* time1, struct timeval* time2) {
|
||||
return (time1->tv_sec - time2->tv_sec) * 1000 + (time1->tv_usec - time2->tv_usec) / 1000;
|
||||
}
|
||||
|
||||
/* */
|
||||
static unsigned long capwap_timeout_set_bitfield(struct capwap_timeout* timeout) {
|
||||
int i, j;
|
||||
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
/* Search free bitfield */
|
||||
for (i = 0; i < CAPWAP_TIMEOUT_BITFIELD_SIZE; i++) {
|
||||
if (timeout->timeoutbitfield[i] != 0xffffffff) {
|
||||
uint32_t bitfield = timeout->timeoutbitfield[i];
|
||||
|
||||
for (j = 0; j < 32; j++) {
|
||||
if (!(bitfield & (1 << j))) {
|
||||
timeout->timeoutbitfield[i] |= (1 << j);
|
||||
return (i * 32 + j + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CAPWAP_TIMEOUT_INDEX_NO_SET;
|
||||
}
|
||||
|
||||
/* */
|
||||
static void capwap_timeout_clear_bitfield(struct capwap_timeout* timeout, unsigned long value) {
|
||||
ASSERT(timeout != NULL);
|
||||
ASSERT(value > 0);
|
||||
|
||||
timeout->timeoutbitfield[(value - 1) / 32] &= ~(1 << ((value - 1) % 32));
|
||||
}
|
||||
|
||||
/* */
|
||||
static void capwap_timeout_additem(struct capwap_list* itemstimeout, struct capwap_list_item* itemlist) {
|
||||
struct capwap_list_item* search;
|
||||
struct capwap_list_item* last = NULL;
|
||||
struct capwap_timeout_item* item = (struct capwap_timeout_item*)itemlist->item;
|
||||
|
||||
/* */
|
||||
search = itemstimeout->first;
|
||||
while (search) {
|
||||
struct capwap_timeout_item* itemsearch = (struct capwap_timeout_item*)search->item;
|
||||
|
||||
if (capwap_timeout_getdelta(&item->expire, &itemsearch->expire) < 0) {
|
||||
capwap_itemlist_insert_before(itemstimeout, last, itemlist);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Next */
|
||||
last = search;
|
||||
search = search->next;
|
||||
}
|
||||
|
||||
/* */
|
||||
if (!search) {
|
||||
capwap_itemlist_insert_after(itemstimeout, NULL, itemlist);
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
static void capwap_timeout_setexpire(long durate, struct timeval* now, struct timeval* expire) {
|
||||
expire->tv_sec = now->tv_sec + durate / 1000;
|
||||
expire->tv_usec = now->tv_usec + durate % 1000;
|
||||
if (expire->tv_usec >= 1000000) {
|
||||
expire->tv_sec++;
|
||||
expire->tv_usec -= 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
struct capwap_timeout* capwap_timeout_init(void) {
|
||||
struct capwap_timeout* timeout;
|
||||
|
||||
/* */
|
||||
timeout = (struct capwap_timeout*)capwap_alloc(sizeof(struct capwap_timeout));
|
||||
memset(timeout, 0, sizeof(struct capwap_timeout));
|
||||
|
||||
/* */
|
||||
timeout->itemsreference = capwap_hash_create(CAPWAP_TIMEOUT_HASH_COUNT);
|
||||
timeout->itemsreference->item_gethash = capwap_timeout_hash_item_gethash;
|
||||
timeout->itemsreference->item_getkey = capwap_timeout_hash_item_getkey;
|
||||
timeout->itemsreference->item_cmp = capwap_timeout_hash_item_cmp;
|
||||
|
||||
timeout->itemstimeout = capwap_list_create();
|
||||
|
||||
return timeout;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_timeout_free(struct capwap_timeout* timeout) {
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
capwap_hash_free(timeout->itemsreference);
|
||||
capwap_list_free(timeout->itemstimeout);
|
||||
capwap_free(timeout);
|
||||
}
|
||||
|
||||
/* */
|
||||
unsigned long capwap_timeout_createtimer(struct capwap_timeout* timeout) {
|
||||
unsigned long index;
|
||||
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
/* Create new timeout index */
|
||||
index = capwap_timeout_set_bitfield(timeout);
|
||||
|
||||
#ifdef CAPWAP_TIMEOUT_LOGGING_DEBUG
|
||||
capwap_logging_debug("Create new timer: %lu", index);
|
||||
#endif
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_timeout_deletetimer(struct capwap_timeout* timeout, unsigned long index) {
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
if (index != CAPWAP_TIMEOUT_INDEX_NO_SET) {
|
||||
#ifdef CAPWAP_TIMEOUT_LOGGING_DEBUG
|
||||
capwap_logging_debug("Delete timer: %lu", index);
|
||||
#endif
|
||||
|
||||
/* Unset timeout timer */
|
||||
capwap_timeout_unset(timeout, index);
|
||||
|
||||
/* Release timer index */
|
||||
capwap_timeout_clear_bitfield(timeout, index);
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
unsigned long capwap_timeout_set(struct capwap_timeout* timeout, unsigned long index, long durate, capwap_timeout_expire callback, void* context, void* param) {
|
||||
struct capwap_list_item* itemlist;
|
||||
struct capwap_timeout_item* item;
|
||||
struct timeval now;
|
||||
|
||||
ASSERT(timeout != NULL);
|
||||
ASSERT(durate >= 0);
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
if (index == CAPWAP_TIMEOUT_INDEX_NO_SET) {
|
||||
index = capwap_timeout_createtimer(timeout);
|
||||
} else {
|
||||
/* Check can update timeout timer */
|
||||
itemlist = (struct capwap_list_item*)capwap_hash_search(timeout->itemsreference, &index);
|
||||
if (itemlist) {
|
||||
/* Remove from timeout list */
|
||||
capwap_itemlist_remove(timeout->itemstimeout, itemlist);
|
||||
|
||||
/* Update timeout */
|
||||
item = (struct capwap_timeout_item*)itemlist->item;
|
||||
item->durate = durate;
|
||||
capwap_timeout_setexpire(item->durate, &now, &item->expire);
|
||||
item->callback = callback;
|
||||
item->context = context;
|
||||
item->param = param;
|
||||
|
||||
#ifdef CAPWAP_TIMEOUT_LOGGING_DEBUG
|
||||
capwap_logging_debug("Update timeout: %lu %ld", item->index, item->durate);
|
||||
#endif
|
||||
|
||||
/* Add itemlist into order list */
|
||||
capwap_timeout_additem(timeout->itemstimeout, itemlist);
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create new timeout timer */
|
||||
itemlist = capwap_itemlist_create(sizeof(struct capwap_timeout_item));
|
||||
item = (struct capwap_timeout_item*)itemlist->item;
|
||||
|
||||
/* */
|
||||
item->index = index;
|
||||
item->durate = durate;
|
||||
capwap_timeout_setexpire(item->durate, &now, &item->expire);
|
||||
item->callback = callback;
|
||||
item->context = context;
|
||||
item->param = param;
|
||||
|
||||
#ifdef CAPWAP_TIMEOUT_LOGGING_DEBUG
|
||||
capwap_logging_debug("Set timeout: %lu %ld", item->index, item->durate);
|
||||
#endif
|
||||
|
||||
/* Add itemlist into hash for rapid searching */
|
||||
capwap_hash_add(timeout->itemsreference, (void*)itemlist);
|
||||
|
||||
/* Add itemlist into order list */
|
||||
capwap_timeout_additem(timeout->itemstimeout, itemlist);
|
||||
|
||||
return item->index;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_timeout_unset(struct capwap_timeout* timeout, unsigned long index) {
|
||||
struct capwap_list_item* itemlist;
|
||||
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
if (index != CAPWAP_TIMEOUT_INDEX_NO_SET) {
|
||||
itemlist = (struct capwap_list_item*)capwap_hash_search(timeout->itemsreference, &index);
|
||||
if (itemlist) {
|
||||
#ifdef CAPWAP_TIMEOUT_LOGGING_DEBUG
|
||||
capwap_logging_debug("Unset timeout: %lu", index);
|
||||
#endif
|
||||
|
||||
/* */
|
||||
capwap_hash_delete(timeout->itemsreference, &index);
|
||||
capwap_itemlist_free(capwap_itemlist_remove(timeout->itemstimeout, itemlist));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_timeout_unsetall(struct capwap_timeout* timeout) {
|
||||
capwap_hash_deleteall(timeout->itemsreference);
|
||||
capwap_list_flush(timeout->itemstimeout);
|
||||
}
|
||||
|
||||
/* */
|
||||
long capwap_timeout_getcoming(struct capwap_timeout* timeout) {
|
||||
long delta;
|
||||
struct timeval now;
|
||||
struct capwap_list_item* search;
|
||||
struct capwap_timeout_item* item;
|
||||
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
/* */
|
||||
search = timeout->itemstimeout->first;
|
||||
if (!search) {
|
||||
return CAPWAP_TIMEOUT_INFINITE;
|
||||
}
|
||||
|
||||
/* */
|
||||
gettimeofday(&now, NULL);
|
||||
item = (struct capwap_timeout_item*)search->item;
|
||||
delta = capwap_timeout_getdelta(&item->expire, &now);
|
||||
|
||||
if (delta <= 0) {
|
||||
return 0;
|
||||
} else if (delta <= item->durate) {
|
||||
return delta;
|
||||
}
|
||||
|
||||
/* Recalculate all timeouts because delta > item->durate */
|
||||
while (search) {
|
||||
struct capwap_timeout_item* itemsearch = (struct capwap_timeout_item*)search->item;
|
||||
|
||||
capwap_timeout_setexpire(itemsearch->durate, &now, &itemsearch->expire);
|
||||
search = search->next;
|
||||
}
|
||||
|
||||
return item->durate;
|
||||
}
|
||||
|
||||
/* */
|
||||
unsigned long capwap_timeout_hasexpired(struct capwap_timeout* timeout) {
|
||||
long delta;
|
||||
struct capwap_timeout_item* item;
|
||||
struct capwap_list_item* itemlist;
|
||||
unsigned long index;
|
||||
capwap_timeout_expire callback;
|
||||
void* context;
|
||||
void* param;
|
||||
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
/* */
|
||||
delta = capwap_timeout_getcoming(timeout);
|
||||
if ((delta > 0) || (delta == CAPWAP_TIMEOUT_INFINITE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
itemlist = capwap_itemlist_remove_head(timeout->itemstimeout);
|
||||
item = (struct capwap_timeout_item*)itemlist->item;
|
||||
|
||||
#ifdef CAPWAP_TIMEOUT_LOGGING_DEBUG
|
||||
capwap_logging_debug("Expired timeout: %lu", item->index);
|
||||
#endif
|
||||
|
||||
/* Cache callback before release timeout timer */
|
||||
index = item->index;
|
||||
callback = item->callback;
|
||||
context = item->context;
|
||||
param = item->param;
|
||||
|
||||
/* Free memory */
|
||||
capwap_hash_delete(timeout->itemsreference, &index);
|
||||
capwap_itemlist_free(itemlist);
|
||||
|
||||
/* */
|
||||
if (callback) {
|
||||
callback(timeout, index, context, param);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_timeout_wait(long durate) {
|
||||
if (durate < 0) {
|
||||
return -1;
|
||||
} else if (durate > 0) {
|
||||
if (usleep((useconds_t)durate * 1000)) {
|
||||
return ((errno == EINTR) ? 0 : -1);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -1,49 +1,49 @@
|
||||
#ifndef __CAPWAP_TIMEOUT_HEADER__
|
||||
#define __CAPWAP_TIMEOUT_HEADER__
|
||||
|
||||
#include "capwap_hash.h"
|
||||
#include "capwap_list.h"
|
||||
|
||||
/* */
|
||||
#define CAPWAP_TIMEOUT_BITFIELD_SIZE 128
|
||||
#define CAPWAP_TIMEOUT_INFINITE -1
|
||||
#define CAPWAP_TIMEOUT_INDEX_NO_SET 0
|
||||
|
||||
/* */
|
||||
struct capwap_timeout {
|
||||
uint32_t timeoutbitfield[CAPWAP_TIMEOUT_BITFIELD_SIZE];
|
||||
struct capwap_hash* itemsreference;
|
||||
struct capwap_list* itemstimeout;
|
||||
};
|
||||
|
||||
/* */
|
||||
typedef void (*capwap_timeout_expire)(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
|
||||
|
||||
struct capwap_timeout_item {
|
||||
unsigned long index;
|
||||
long durate;
|
||||
struct timeval expire;
|
||||
capwap_timeout_expire callback;
|
||||
void* context;
|
||||
void* param;
|
||||
};
|
||||
|
||||
/* */
|
||||
struct capwap_timeout* capwap_timeout_init(void);
|
||||
void capwap_timeout_free(struct capwap_timeout* timeout);
|
||||
|
||||
/* */
|
||||
unsigned long capwap_timeout_createtimer(struct capwap_timeout* timeout);
|
||||
void capwap_timeout_deletetimer(struct capwap_timeout* timeout, unsigned long index);
|
||||
|
||||
/* */
|
||||
unsigned long capwap_timeout_set(struct capwap_timeout* timeout, unsigned long index, long durate, capwap_timeout_expire callback, void* context, void* param);
|
||||
void capwap_timeout_unset(struct capwap_timeout* timeout, unsigned long index);
|
||||
void capwap_timeout_unsetall(struct capwap_timeout* timeout);
|
||||
|
||||
long capwap_timeout_getcoming(struct capwap_timeout* timeout);
|
||||
unsigned long capwap_timeout_hasexpired(struct capwap_timeout* timeout);
|
||||
|
||||
int capwap_timeout_wait(long durate);
|
||||
|
||||
#endif /* __CAPWAP_TIMEOUT_HEADER__ */
|
||||
#ifndef __CAPWAP_TIMEOUT_HEADER__
|
||||
#define __CAPWAP_TIMEOUT_HEADER__
|
||||
|
||||
#include "capwap_hash.h"
|
||||
#include "capwap_list.h"
|
||||
|
||||
/* */
|
||||
#define CAPWAP_TIMEOUT_BITFIELD_SIZE 128
|
||||
#define CAPWAP_TIMEOUT_INFINITE -1
|
||||
#define CAPWAP_TIMEOUT_INDEX_NO_SET 0
|
||||
|
||||
/* */
|
||||
struct capwap_timeout {
|
||||
uint32_t timeoutbitfield[CAPWAP_TIMEOUT_BITFIELD_SIZE];
|
||||
struct capwap_hash* itemsreference;
|
||||
struct capwap_list* itemstimeout;
|
||||
};
|
||||
|
||||
/* */
|
||||
typedef void (*capwap_timeout_expire)(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
|
||||
|
||||
struct capwap_timeout_item {
|
||||
unsigned long index;
|
||||
long durate;
|
||||
struct timeval expire;
|
||||
capwap_timeout_expire callback;
|
||||
void* context;
|
||||
void* param;
|
||||
};
|
||||
|
||||
/* */
|
||||
struct capwap_timeout* capwap_timeout_init(void);
|
||||
void capwap_timeout_free(struct capwap_timeout* timeout);
|
||||
|
||||
/* */
|
||||
unsigned long capwap_timeout_createtimer(struct capwap_timeout* timeout);
|
||||
void capwap_timeout_deletetimer(struct capwap_timeout* timeout, unsigned long index);
|
||||
|
||||
/* */
|
||||
unsigned long capwap_timeout_set(struct capwap_timeout* timeout, unsigned long index, long durate, capwap_timeout_expire callback, void* context, void* param);
|
||||
void capwap_timeout_unset(struct capwap_timeout* timeout, unsigned long index);
|
||||
void capwap_timeout_unsetall(struct capwap_timeout* timeout);
|
||||
|
||||
long capwap_timeout_getcoming(struct capwap_timeout* timeout);
|
||||
unsigned long capwap_timeout_hasexpired(struct capwap_timeout* timeout);
|
||||
|
||||
int capwap_timeout_wait(long durate);
|
||||
|
||||
#endif /* __CAPWAP_TIMEOUT_HEADER__ */
|
||||
|
Reference in New Issue
Block a user