More work on CW VM code ..

FossilOrigin-Name: 3b0cb324535527b32d0e938b03151c75f6100ca2059fc121e2c4d350a8caf8a4
bsdmakefiles
7u83@mail.ru 9 years ago
parent e148b7c9f6
commit c43f85b2a6
  1. 2
      src/ac/Makefile
  2. 2
      src/ac/ac_global.c
  3. 22
      src/ac/ac_main.c
  4. 13
      src/ac/wtpman.c
  5. 2
      src/capwap/Doxyfile
  6. 28
      src/capwap/Makefile
  7. 5
      src/capwap/aciplist.c
  8. 4
      src/capwap/aciplist.h
  9. 60
      src/capwap/avltree.h
  10. 3
      src/capwap/avltree_foreach_from_lr.c
  11. 56
      src/capwap/capwap.h
  12. 29
      src/capwap/capwap_80211.h
  13. 13
      src/capwap/capwap_action_helpers.c
  14. 29
      src/capwap/capwap_actions.h
  15. 12
      src/capwap/capwap_actions_ac.c
  16. 59
      src/capwap/capwap_actions_wtp.c
  17. 8
      src/capwap/capwap_items.h
  18. 2
      src/capwap/capwap_strings_elem.c
  19. 2
      src/capwap/capwap_strings_item.c
  20. 2
      src/capwap/capwap_strings_msg.c
  21. 2
      src/capwap/capwap_strings_state.c
  22. 3
      src/capwap/capwap_strings_vendor.c
  23. 12
      src/capwap/conn.h
  24. 1
      src/capwap/conn_init.c
  25. 433
      src/capwap/conn_process_packet.c
  26. 42
      src/capwap/cw_check_missing_mand.c
  27. 5
      src/capwap/cw_in_check_disc_req.c
  28. 17
      src/capwap/cw_in_check_disc_resp.c
  29. 11
      src/capwap/cw_in_check_img_data_req.c
  30. 4
      src/capwap/cw_in_check_join_req.c
  31. 2
      src/capwap/cw_in_cisco_image_identifier.c
  32. 34
      src/capwap/cw_in_generic.c
  33. 2
      src/capwap/cw_in_wtp_board_data.c
  34. 2
      src/capwap/cw_in_wtp_descriptor.c
  35. 4
      src/capwap/cw_log.h
  36. 104
      src/capwap/cw_log_debug.c
  37. 6
      src/capwap/cw_out_ac_descriptor.c
  38. 4
      src/capwap/cw_out_capwap_control_ip_addr_list.c
  39. 4
      src/capwap/cw_out_cisco_ac_descriptor.c
  40. 44
      src/capwap/cw_out_generic.c
  41. 84
      src/capwap/cw_out_wtp_board_data.c
  42. 2
      src/capwap/cw_process_msg.c
  43. 2
      src/capwap/cw_strlist_get_str.c
  44. 6
      src/capwap/cw_util.h
  45. 51
      src/capwap/dbg.c
  46. 21
      src/capwap/dbg.h
  47. 12
      src/capwap/dtls_gnutls.c
  48. 1
      src/capwap/dtls_gnutls.h
  49. 2
      src/capwap/dtls_gnutls_accept.c
  50. 2
      src/capwap/dtls_gnutls_bio.c
  51. 1
      src/capwap/format.h
  52. 1
      src/capwap/intavltree.h
  53. 9
      src/capwap/itemstore.c
  54. 36
      src/capwap/itemstore.h
  55. 4
      src/capwap/strheap.h
  56. 2
      src/wtp/Makefile
  57. 154
      src/wtp/discovery.c
  58. 123
      src/wtp/join.c
  59. 19
      src/wtp/wtp_main.c

@ -11,7 +11,7 @@ ifndef ARCH
endif
LDFLAGS+=-g -D_REENTRANT -L/usr/local/lib -L../capwap/$(ARCH)
CFLAGS += -Wall -g -O0 -D_REENTRANT -DIPV6 -I/usr/local/include -I../
CFLAGS += -Wall -g -O3 -D_REENTRANT -DIPV6 -I/usr/local/include -I../
LIBS+=-lcapwap

@ -104,7 +104,7 @@ int ac_global_init()
// cw_itemstore_set_avltree(ac_config, CW_ITEM_AC_IP_LIST, aciplist);
cw_itemstore_set_fun(ac_config, CW_ITEM_CAPWAP_CONTROL_IP_LIST, get_iplist,release_iplist,(void*)771);
cw_itemstore_set_fun(ac_config, CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST, get_iplist,release_iplist,(void*)771);
return 1;
}

@ -105,7 +105,29 @@ int readelem_cisco_rad_name(struct conn *conn,struct cw_action * a,uint8_t *data
int main (int argc, const char * argv[])
{
/*
intavltree_t t = intavltree_create();
int i;
for (i=0; i<100; i++){
intavltree_add(t,i);
}
avliter_t iter;
avliter_init(&iter,t);
int *val;
for (avliter_seek_set(&iter); val = avliter_get(&iter); avliter_next(&iter)){
printf("Val is: %d\n",*val);
}
exit(0);
*/
cw_log_name="AC-Tube";
read_config("ac.conf");

@ -117,15 +117,15 @@ static void wtpman_run_discovery(void *arg)
*/
wtpman->conn->local = ac_config;
wtpman->conn->remote = cw_itemstore_create();
wtpman->conn->outgoing = ac_config;
wtpman->conn->incomming = cw_itemstore_create();
while (!cw_timer_timeout(timer)
&& wtpman->conn->capwap_state == CW_STATE_DISCOVERY) {
cw_read_messages(wtpman->conn);
}
struct cw_item *wn = cw_itemstore_get(wtpman->conn->remote, CW_ITEM_WTP_NAME);
struct cw_item *wn = cw_itemstore_get(wtpman->conn->incomming, CW_ITEM_WTP_NAME);
if (wn) {
printf("WTP Name: %s\n", wn->data);
@ -282,8 +282,8 @@ static int wtpman_join(void *arg, time_t timer)
// wtpman->conn->itemstore = cw_itemstore_create();
wtpman->conn->local = ac_config;
wtpman->conn->remote = cw_itemstore_create();
wtpman->conn->outgoing = ac_config;
wtpman->conn->incomming = cw_itemstore_create();
while (!cw_timer_timeout(timer) && wtpman->conn->capwap_state == CW_STATE_JOIN) {
int rc = cw_read_messages(wtpman->conn);
@ -305,7 +305,7 @@ static int wtpman_join(void *arg, time_t timer)
}
/*
static int wtpman_send_image_file(struct wtpman *wtpman, struct cwrmsg *cwrmsg)
{
struct cwimage_data data;
@ -343,6 +343,7 @@ static int wtpman_send_image_file(struct wtpman *wtpman, struct cwrmsg *cwrmsg)
return 0;
}
*/
static void wtpman_run(void *arg)
{

@ -1352,7 +1352,7 @@ DISABLE_INDEX = NO
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
GENERATE_TREEVIEW = YES
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.

@ -32,7 +32,7 @@ SOCKOBJS=sock_create.o sock_copyaddr.o sock_strtoaddr.o sock_cmpaddr.o sock_addr
sock_addrinit.o \
sock_set_dontfrag.o \
sock_get_primary_if.o \
#sock_receive.o \
sock_receive.o \
LOGOBJS=cw_log.o \
cw_log_debug.o \
@ -59,10 +59,13 @@ UTILOBJS= \
avltree_foreach_lr.o \
avltree_foreach_rl.o \
avltree_foreach_from_lr.o \
avliter_next.o \
avliter_seek.o \
stravltree.o \
intavltree.o \
cw_util.o \
cw_format_version.o \
send.o
@ -97,7 +100,6 @@ CAPWAPOBJS= \
cwmsg_vaddelem.o \
cwmsg_addelem_ac_descriptor.o \
cwmsg_addelem_wtp_descriptor.o \
cwmsg_addelem_wtp_radio_infos.o \
cwmsg_addelem_cw_local_ip_addr.o \
cwmsg_addelem_mtu_discovery_padding.o \
cwmsg_addelem_ac_timestamp.o \
@ -122,9 +124,6 @@ CAPWAPOBJS= \
cwread_wtp_event_request.o \
process_conf_status_request.o \
wtpinfo_readelem_wtp_mac_type.o \
wtpinfo_readelem_wtp_radio_info.o \
cw_readelem_80211_wtp_radio_info.o \
cwmsg_addelem_80211_add_wlan.o \
wtpinfo_readelem_wtp_descriptor.o \
wtpinfo_readelem_discovery_type.o \
wtpinfo_readelem_wtp_frame_tunnel_mode.o \
@ -159,6 +158,8 @@ CAPWAPOBJS= \
cw_addelem_cisco_wtp_radio_cfg.o \
cw_strlist_get_str.o \
capwap_strings_msg.o \
capwap_strings_elem80211.o\
acpriolist.o\
capwap_strings_state.o \
capwap_strings_vendor.o \
capwap_strings_elem.o \
@ -166,21 +167,26 @@ CAPWAPOBJS= \
cw_in_vendor_specific_payload.o \
cw_in_wtp_board_data.o \
cw_in_check_disc_req.o \
cw_in_check_disc_resp.o\
cw_in_check_join_req.o \
cw_in_check_join_resp.o \
cw_in_check_img_data_req.o \
cw_out_generic.o \
cw_out_ac_descriptor.o \
cw_out_cisco_ac_descriptor.o \
cw_out_cisco_ap_timesync.o \
cw_in_cisco_image_identifier.o\
cw_out_capwap_control_ip_addrs.o \
cw_out_capwap_control_ip_addr_list.o \
cw_in_capwap_control_ipv4_address.o\
strheap.o \
cw_check_missing_mand.o \
dbg.o \
md5sum.o \
format.o
format.o \
# cwmsg_addelem_wtp_radio_infos.o \
# cw_addelem_vendor_specific_payload.o \
#cw_in_wtp_name.o \
#cw_msgtostr.o \
@ -191,10 +197,13 @@ CAPWAPOBJS= \
#wtpinfo_readelem_wtp_board_data.o \
# cw_send_image_data_response.o \
#cwmsg_init.o \
# cw_readelem_80211_wtp_radio_info.o \
# cwmsg_addelem_80211_add_wlan.o \
#cw_ianavendoridtostr.o \
#cwmsg_addelem_result_code.o \
# cwmsg_addelem_radio_operational_state.o \
# wtpinfo_readelem_wtp_radio_info.o \
# cwmsg_addelem_vendor_cisco_ap_timesync.o \
# cwmsg_addelem_vendor_specific_payload.o \
@ -273,17 +282,20 @@ BSTROBJS= bstr_create.o \
FRAGOBJS=fragman.o
CWACTION=action.o \
cw_process_msg.o \
capwap_actions_ac.o \
capwap_actions_wtp.o \
capwap_80211_actions_wtp.o \
cw_in_generic.o \
cw_in_wtp_descriptor.o \
cw_out_wtp_board_data.o \
cipwap_actions_ac.o \
cipwap_strings_elem.o \
capwap_strings_result.o\
cw_put_msg.o \
capwap_action_helpers.o \
# cw_process_msg.o \
OBJS=$(CONNOBJS) $(FRAGOBJS) $(SOCKOBJS) $(CAPWAPOBJS) $(WTPINFOOBJS) \

@ -32,6 +32,11 @@ static int acip_cmp(const void *x1, const void *x2)
{
struct cw_acip *ip1 = (struct cw_acip *) x1;
struct cw_acip *ip2 = (struct cw_acip *) x2;
int r = ip1->wtp_count - ip2->wtp_count;
if (r!=0)
return r;
if (ip1->ip.ss_family != ip2->ip.ss_family) {
if (ip1->ip.ss_family == AF_INET)

@ -5,7 +5,7 @@
struct cw_acip{
struct sockaddr_storage ip;
int wtp_count;
uint32_t wtp_count;
};
typedef struct cw_acip cw_acip_t;
@ -16,7 +16,9 @@ extern cw_aciplist_t cw_aciplist_create();
#define cw_aciplist_destroy(l) avltree_destroy(l)
#define cw_aciplist_add(l,elem) avltree_add(l,elem)
#define cw_aciplist_del(l,elem) avltree_del(l,elem)
#define cw_aciplist_foreach(l,callback,cbpriv) avltree_foreach_asc(l,callback,cbpriv)
#define cw_aciplist_replace(l,r) avltree_replace(l,r)
#endif

@ -30,8 +30,15 @@
#include <stdint.h>
/** Maximum AVL Tree depth.
The number of nodes is calculated by 2^depth.
So a value of 32 should be enough for around 4
billion nodes. */
#define AVLTREE_MAX_DEPTH 32
/**
* Defines the structure of an AVL Node.
*/
struct avlnode {
void *data;
struct avlnode *left;
@ -39,7 +46,9 @@ struct avlnode {
int bal;
};
/**
* AVL Tree
*/
struct avltree {
struct avlnode *root;
int (*cmp) (const void *, const void *);
@ -81,6 +90,16 @@ static inline void *avltree_replace_data(struct avltree *t, void *data, int len)
return df;
}
static inline void *avltree_replace(struct avltree *t,void *data){
struct avlnode * node = avltree_get_node(t,data);
if (node){
t->del(node->data);
return node->data=data;
}
return avltree_add(t,data);
}
static inline void avltree_destroy(struct avltree *t)
{
avltree_del_all(t);
@ -106,6 +125,7 @@ struct avliter{
struct avlnode *cur;
int stack_ptr;
struct avlnode * root;
int (*cmp) (const void *, const void *);
};
typedef struct avliter avliter_t;
@ -113,23 +133,35 @@ typedef struct avliter avliter_t;
void * avliter_next(avliter_t *i);
void * avliter_seek_set(struct avliter *i)
static inline void * avliter_seek_set(struct avliter *i)
{
i->stack_ptr=0;
i->cur=i->root;
return avliter_next(i);
}
/**
* Init an AVL Tree Iterator.
*
* After initialization #avliter_next would return the first element.
* The behavior of #avliter_get would still be undefined.
* @param i AVL Iterator to initialize
* @param t correspondending AVL Tree
*
* @See avliter_t,
*/
static inline void avliter_init(avliter_t *i, avltree_t t){
i->root = t->root;
i->stack_ptr=0;
i->cmp=t->cmp;
}
#define avliter_foreach_asc(iter,val) \
while(NULL != (val = avliter_next(iter)))
/**
* Get the element, where AVL Iterator currently is positioned.
* @param i AVL Iterator
* @return element or NULL if not found.
*/
static inline void * avliter_get(avliter_t *i){
if(!i->cur)
return NULL;
@ -137,7 +169,23 @@ static inline void * avliter_get(avliter_t *i){
}
extern void * avliter_seek(avliter_t *i,void *d);
#define DEFINE_AVLITER(i,t)\
avliter_t i; avliter_init(&i,t)
#define avliter_foreach(i)\
for (avliter_seek_set(i); NULL != avliter_get(i); avliter_next(i))
#define avliter_foreach_from(i,from)\
for (avliter_seek(i,from); NULL != avliter_get(i); avliter_next(i))
#define avliter_foreach_asc(iter,val) \
while(NULL != (val = avliter_next(iter)))
#endif

@ -1,5 +1,8 @@
#include "avltree.h"
// XXX Function is buggy
int avltree_foreach_from_lr(struct avltree *t, struct avlnode *n, void *data,int (*callback)(void *,void *),void *cbpriv)
{
if (!n)

@ -454,12 +454,12 @@ extern int cw_readelem_vendor_specific_payload(void *data, int msgtype, int elem
#define CW_RESULT_SUCCESS 0
#define CW_RESULT_FAILURE 1
#define CW_RESULT_MISSING_AC_LIST 1
#define CW_RESULT_SUCCESS_NAT 2
#define CW_RESULT_JOIN_FAILURE 3
#define CW_RESULT_JOIN_RESOURCE_DEPLETION 4
#define CW_RESULT_JOIN_UNKNOWN_SOURCE 5
#define CW_RESULT_JOIN_FAILURE_INCORRECT_DATA 6
#define CW_RESULT_JOIN_INCORRECT_DATA 6
#define CW_RESULT_JOIN_FAILURE_SESSION_ALREADY_IN_USE 7
#define CW_RESULT_JOIN_FAILURE_WTP_HARDWARE_NOT_SUPPORTED 8
#define CW_RESULT_JOIN_FAILURE_BINDING_NOT_SUPPORTED 9
@ -641,6 +641,15 @@ static inline uint8_t *cw_get_hdr_msg_elems_ptr(uint8_t * m)
return cw_get_msg_elems_ptr(m + cw_get_hdr_msg_offset(m));
}
static inline uint8_t * cw_get_hdr_msg_ptr(uint8_t *rawmsg)
{
return rawmsg + cw_get_hdr_msg_offset(rawmsg);
}
#define cw_get_hdr_msg_id(ptr)\
cw_get_msg_id(cw_get_hdr_msg_ptr(ptr))
#define cw_get_hdr_msg_type cw_get_hdr_msg_id
static inline int cw_get_hdr_msg_total_len(uint8_t * rawmsg)
{
@ -836,19 +845,21 @@ extern struct cw_str capwap_strings_msg[];
extern struct cw_str capwap_strings_state[];
extern struct cw_str capwap_strings_vendor[];
extern struct cw_str capwap_strings_elem[];
extern struct cw_str capwap_strings_result[];
#define cw_strmsg(id) cw_strlist_get_str(capwap_strings_msg,id)
#define cw_strelem(id) cw_strlist_get_str(capwap_strings_elem,id)
#define cw_strstate(id) cw_strlist_get_str(capwap_strings_state,id)
#define cw_strvendor(id) cw_strlist_get_str(capwap_strings_vendor,id)
#define cw_strresult(id) cw_strlist_get_str(capwap_strings_result,(id))
static inline const char * cw_strelemp_(cw_strheap_t h, int msg_id) {
const char * rc = cw_strheap_get(h,msg_id);
if (rc)
return rc;
return cw_strheap_get(h,0);
return cw_strheap_get(h,CW_STR_STOP);
}
#define cw_strelemp(p,id) cw_strelemp_((p)->strelem,id)
@ -858,7 +869,7 @@ extern const char *cw_strlist_get_str(struct cw_str *s, int id);
int cw_process_msg(struct conn *conn, uint8_t * rawmsg, int len);
//int cw_process_msg(struct conn *conn, uint8_t * rawmsg, int len);
extern int cw_in_generic(struct conn *conn, struct cw_action_in *a, uint8_t * data,
@ -871,6 +882,8 @@ extern int cw_in_wtp_board_data(struct conn *conn, struct cw_action_in *a, uint8
int len);
extern int cw_in_wtp_descriptor(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len);
extern int cw_in_capwap_control_ipv4_address(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len);
//extern int cw_out_generic(struct conn *conn,struct cw_action_in * a,uint8_t *data,int len);
extern int cw_out_generic(struct conn *conn, struct cw_action_out *a, uint8_t * dst); //, struct cw_item *item);
@ -882,7 +895,7 @@ extern int cw_out_ac_descriptor(struct conn *conn,struct cw_action_out * a,uint8
//extern int cw_out_capwap_control_ip_addrs(struct conn *conn, uint32_t elem_id,
// uint8_t * dst, struct cw_item *item);
extern int cw_out_capwap_control_ip_addrs(struct conn *conn,struct cw_action_out *a,uint8_t *dst) ;
extern int cw_out_capwap_control_ip_addr_list(struct conn *conn,struct cw_action_out *a,uint8_t *dst) ;
extern int cw_put_msg(struct conn *conn, uint8_t * rawout);
@ -932,8 +945,15 @@ int cw_register_actions_capwap_wtp(struct cw_actiondef *def);
int cw_in_set_state_none(struct conn *conn,struct cw_action_in * a,uint8_t *data,int len);
struct cw_item *cw_out_get_outgoing(struct conn *conn, struct cw_action_out *a);
struct cw_item *cw_out_get_local(struct conn *conn, struct cw_action_out *a);
extern int cw_in_check_join_resp(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len);
extern int cw_in_check_disc_req(struct conn *conn,struct cw_action_in * a,uint8_t *data,int len);
int cw_in_check_disc_resp(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len);
int cw_check_missing_mand(cw_action_in_t ** out, struct conn * conn, cw_action_in_t *a);
int cw_in_check_join_req(struct conn *conn, struct cw_action_in *a, uint8_t * data, int len);
int cw_in_check_img_data_req(struct conn *conn, struct cw_action_in *a, uint8_t * data,
@ -945,4 +965,30 @@ void cw_init_request(struct conn *conn,int msg_id);
/**
* @defgroup TimerFunctions Timer functions
* @{
*/
/**
* Start a timer.
* @param t number of seconds until the timer expires
* @return timer value to initialize a variable of time_t
*
* Example: time_t timer = cw_timer_start(60);
*/
#define cw_timer_start(t) (time(NULL)+t)
/**
* Check if a timer is expired.
* @param t an time_t variable intializes by #cw_timer_start
* @return 0=timer is not expired\n 1=timer is expired.
*/
#define cw_timer_timeout(t) (time(NULL)>t ? 1 : 0)
/** @} */
int cw_send_request(struct conn *conn,int msg_id);
#endif

@ -1,4 +1,11 @@
#ifndef __CAPWAP_80211
#define __CAPWAP_80211
#include "capwap.h"
#include <stdint.h>
#include "bstr.h"
#include "action.h"
#define CW80211IANA_ENTERPRISE_NUMBER 13277
@ -8,8 +15,8 @@
#define CW_ELEM_80211_ADD_WLAN 1024
#define CW_ELEM_80211_ANTENNA 1025
#define CW_ELEM80211_ADD_WLAN 1024
#define CW_ELEM80211_ANTENNA 1025
/*
IEEE 802.11 Assigned WTP BSSID 1026
IEEE 802.11 Delete WLAN 1027
@ -35,7 +42,7 @@
IEEE 802.11 WTP Radio Fail Alarm Indication 1047
*/
#define CWMSGELEM_80211_WTP_RADIO_INFO 1048
#define CW_ELEM80211_WTP_RADIO_INFORMATION 1048
@ -45,14 +52,6 @@
/*
#define CW_IEEE80211_RADIO_TYPE_B (1<<24)
#define CW_IEEE80211_RADIO_TYPE_A (2<<24)
#define CW_IEEE80211_RADIO_TYPE_G (4<<24)
#define CW_IEEE80211_RADIO_TYPE_N (8<<24)
*/
#define CW_80211_RADIO_TYPE_B (1)
#define CW_80211_RADIO_TYPE_A (2)
#define CW_80211_RADIO_TYPE_G (4)
@ -62,7 +61,7 @@
struct cwwlan {
struct cw_wlan {
uint8_t rid; /* Radio ID */
uint8_t wid; /* WLAN ID */
uint16_t capab;
@ -77,16 +76,18 @@ struct cwwlan {
uint8_t tunnel_mode;
uint8_t suppress_ssid;
bstr_t ssid;
};
extern int cw_readelem_ieee80211_wtp_radio_info(void *dst,int type,uint8_t *msgelem, int len);
extern int cw_register_actions_capwap_80211_wtp(struct cw_actiondef *def);
extern struct cw_str capwap_strings_elem80211[];
#endif

@ -11,14 +11,19 @@ int cw_in_set_state_none(struct conn *conn,struct cw_action_in * a,uint8_t *data
return 1;
}
struct cw_item *cw_out_get_local(struct conn *conn, struct cw_action_out *a)
struct cw_item *cw_out_get_outgoing(struct conn *conn, struct cw_action_out *a)
{
return cw_itemstore_get(conn->local, a->item_id);
return cw_itemstore_get(conn->outgoing, a->item_id);
}
struct cw_item *cw_out_get_remote(struct conn *conn, struct cw_action_out *a)
struct cw_item *cw_out_get_incomming(struct conn *conn, struct cw_action_out *a)
{
return cw_itemstore_get(conn->local, a->item_id);
return cw_itemstore_get(conn->incomming, a->item_id);
}
struct cw_item *cw_out_get_local(struct conn *conn, struct cw_action_out *a)
{
return cw_itemstore_get(conn->local,a->item_id);
}

@ -58,7 +58,7 @@
cw_in_generic, 0, /* start/end callback */ \
CW_ITEMTYPE_STR, /* Type of element */ \
CW_ITEM_AC_NAME, /* ID to use store */ \
1, 1024 /* min/max length */
1, 512 /* min/max length */
#define CW_ACTION_IN_STATISTICS_TIMER \
CW_ELEM_STATISTICS_TIMER, /* Element ID*/ \
@ -114,10 +114,35 @@
#define CW_ACTION_IN_CAPWAP_CONTROL_IPV4_ADDRESS \
CW_ELEM_CAPWAP_CONTROL_IPV4_ADDRESS, /* Element ID*/ \
cw_in_capwap_control_ipv4_address, 0, /* start/end callback */ \
CW_ITEMTYPE_AVLTREE, /* Type of element */ \
CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST, /* ID to use store */ \
6, 6 /* min/max length */
#define CW_ACTION_IN_CAPWAP_CONTROL_IPV6_ADDRESS \
CW_ELEM_CAPWAP_CONTROL_IPV6_ADDRESS, /* Element ID*/ \
cw_in_capwap_control_iv4p_address, 0, /* start/end callback */ \
CW_ITEMTYPE_AVLTREE, /* Type of element */ \
CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST, /* ID to use store */ \
18,18 /* min/max length */
#define CW_ACTION_IN_AC_DESCRIPTOR \
CW_ELEM_AC_DESCRIPTOR, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
CW_ITEMTYPE_DATA, /* Type of element */ \
CW_ITEM_CAPWAP_CONTROL_IP_ADDR, /* ID to use store */ \
CW_ITEM_AC_DESCRIPTOR, /* ID to use store */ \
6, 6 /* min/max length */
#define CW_ACTION_IN_RESULT_CODE \
CW_ELEM_RESULT_CODE, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
CW_ITEMTYPE_DWORD, /* Type of element */ \
CW_ITEM_RESULT_CODE, /* ID to use store */ \
4, 4 /* min/max length */
#endif

@ -153,12 +153,12 @@ cw_action_out_t capwap_actions_ac_out[] = {
/* AC Name */
{CW_MSG_DISCOVERY_RESPONSE, CW_ITEM_AC_NAME, 0,
CW_ELEM_AC_NAME, cw_out_generic, cw_out_get_local}
CW_ELEM_AC_NAME, cw_out_generic, cw_out_get_outgoing}
,
/* List of CAPWAP Control IPv4 and IPv6 addresses */
{CW_MSG_DISCOVERY_RESPONSE, CW_ITEM_CAPWAP_CONTROL_IP_LIST, 0,
0, cw_out_capwap_control_ip_addrs, cw_out_get_local}
{CW_MSG_DISCOVERY_RESPONSE, CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST, 0,
0, cw_out_capwap_control_ip_addr_list, cw_out_get_outgoing}
,
@ -170,7 +170,7 @@ cw_action_out_t capwap_actions_ac_out[] = {
/* Result Code */
{CW_MSG_JOIN_RESPONSE, CW_ITEM_RESULT_CODE, 0,
CW_ELEM_RESULT_CODE, cw_out_generic, cw_out_get_local, 1}
CW_ELEM_RESULT_CODE, cw_out_generic, cw_out_get_outgoing, 1}
,
/* AC Descriptor */
@ -180,7 +180,7 @@ cw_action_out_t capwap_actions_ac_out[] = {
/* AC Name */
{CW_MSG_JOIN_RESPONSE, CW_ITEM_AC_NAME, 0,
CW_ELEM_AC_NAME, cw_out_generic, cw_out_get_local}
CW_ELEM_AC_NAME, cw_out_generic, cw_out_get_outgoing}
,
@ -194,7 +194,7 @@ cw_action_out_t capwap_actions_ac_out[] = {
/* Result Code */
{CW_MSG_IMAGE_DATA_RESPONSE, CW_ITEM_RESULT_CODE, 0,
CW_ELEM_RESULT_CODE, cw_out_generic, cw_out_get_local, 1}
CW_ELEM_RESULT_CODE, cw_out_generic, cw_out_get_outgoing, 1}
,

@ -32,20 +32,43 @@ cw_action_in_t capwap_actions_wtp_in[] = {
/* Message Discovery Response */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_RESPONSE, 0,
0, 0}
0, cw_in_check_disc_resp}
,
/* AC Descriptor */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_RESPONSE,
CW_ACTION_IN_AC_DESCRIPTOR, 1}
,
/* Element: AC Name */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_RESPONSE,
CW_ACTION_IN_AC_NAME, 1}
,
/* Element CAPWAP Control IPv4 Address */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_RESPONSE,
CW_ACTION_IN_CAPWAP_CONTROL_IPV4_ADDRESS, 1}
,
/* Element: Vendor Specific */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_RESPONSE,
CW_ACTION_IN_VENDOR_SPECIFIC_PAYLOAD, 1}
CW_ACTION_IN_VENDOR_SPECIFIC_PAYLOAD, 0}
,
/* Element CAPWAP Control IPv4 Address */
/* ------------------------------------------------------------------------------- */
/* Message Join Response */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_RESPONSE, 0,
0, cw_in_check_join_resp }
,
/* Element: Vendor Specific */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_RESPONSE,
CW_ACTION_IN_RESULT_CODE, 1}
,
{0, 0, 0}
@ -56,21 +79,43 @@ cw_action_in_t capwap_actions_wtp_in[] = {
cw_action_out_t capwap_actions_wtp_out[] = {
/* -------------------------------------------------------------------------------
* Discovery Request OUT
*/
{CW_MSG_DISCOVERY_REQUEST, CW_ITEM_NONE}
,
/* AC Name */
{CW_MSG_DISCOVERY_REQUEST, CW_ITEM_DISCOVERY_TYPE, 0,
CW_ELEM_DISCOVERY_TYPE, cw_out_generic, cw_out_get_local}
CW_ELEM_DISCOVERY_TYPE, cw_out_generic, cw_out_get_outgoing}
,
/* AC Name */
/* WTP Board Data */
{CW_MSG_DISCOVERY_REQUEST, CW_ITEM_WTP_BOARD_DATA, 0,
CW_ELEM_WTP_BOARD_DATA, cw_out_wtp_board_data, cw_out_get_local}
CW_ELEM_WTP_BOARD_DATA, cw_out_wtp_board_data, cw_out_get_outgoing}
,
/* -------------------------------------------------------------------------------
* Join Request OUT
*/
{CW_MSG_JOIN_REQUEST, CW_ITEM_NONE}
,
/* Location Data */
{CW_MSG_JOIN_REQUEST, CW_ITEM_LOCATION_DATA, 0,
CW_ELEM_LOCATION_DATA, cw_out_generic, cw_out_get_local,1}
,
/* WTP Name */
{CW_MSG_JOIN_REQUEST, CW_ITEM_WTP_NAME, 0,
CW_ELEM_WTP_NAME, cw_out_generic, cw_out_get_local,1}
,
{0, 0}

@ -35,7 +35,7 @@ enum capwap_items {
CW_ITEM_AC_SOFTWARE_VERSION,
CW_ITEM_AC_IP_LIST,
CW_ITEM_CAPWAP_CONTROL_IP_LIST,
CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST,
CW_ITEM_LOCATION_DATA,
CW_ITEM_SESSION_ID,
@ -52,8 +52,10 @@ enum capwap_items {
/* Other Items */
CW_ITEM_AC_IMAGE_DIR, /* Path where image WTP images are stored */
CW_ITEM_WTP_IMAGE_FILENAME /* Full path of image filename */
CW_ITEM_AC_IMAGE_DIR, /* Path where WTP images are stored */
CW_ITEM_WTP_IMAGE_FILENAME, /* Full path of image filename */
CW_ITEM_DISCOVERIES,
CW_ITEM_AC_PRIO_LIST /* AC Name with Priority list */
};

@ -62,6 +62,6 @@ struct cw_str capwap_strings_elem[] = {
/* CW_ELEM_WTP_IPV4_IP_ADDRESS 42
CW_ELEM_WTP_IPV6_IP_ADDRESS 43
*/
{0,"Unknown Element"}
{CW_STR_STOP,"Unknown Element"}
};

@ -4,6 +4,6 @@ struct cw_str capwap_strings_item[] = {
{CW_ITEM_AC_IPV4_LIST, "AC IPv4 List"},
{CW_ITEM_WTP_DESCRIPTOR,"WTP Descriptor"},
{CW_STR_STOP,"Unknown"}
}

@ -30,7 +30,7 @@ struct cw_str capwap_strings_msg[] = {
Station Configuration Response 26
*/
{0,"Unknown Message Type"}
{CW_STR_STOP,"Unknown Message Type"}
};

@ -5,6 +5,6 @@ struct cw_str capwap_strings_state[] = {
{ CW_STATE_JOIN,"Join" },
{ CW_STATE_RUN,"Run" },
{ CW_STATE_CONFIGURE,"Configure" },
{ 0,"Undefined" }
{ CW_STR_STOP,"Undefined" }
};

@ -4,5 +4,6 @@
struct cw_str capwap_strings_vendor[] = {
{ CW_VENDOR_ID_CISCO, "Cisco" },
{ CW_VENDOR_ID_ZYXEL, "Zyxel" },
{ CW_VENDOR_ID_FSF, "FSF"}
{ CW_VENDOR_ID_FSF, "FSF"},
{ CW_STR_STOP, "Unknown" }
};

@ -48,11 +48,11 @@ struct conn {
struct sockaddr_storage addr;
int recv_timeout;
/** Basically used to store local conig data */
cw_itemstore_t local;
/** used to maintain the remote config, an AC holds here the WTP config.
A WTP holds here data about it's AC */
cw_itemstore_t outgoing;
cw_itemstore_t incomming;
cw_itemstore_t remote;
cw_itemstore_t local;
/** Counter for mandatory message elements */
struct avltree *mand;
@ -170,8 +170,8 @@ struct conn *conn_create_noq(int sock, struct sockaddr *addr);
extern int conn_send_cwmsg(struct conn *conn, struct cwmsg *cwmsg);
extern int conn_process_packet(struct conn *conn, uint8_t * packet, int len,
int (*cb) (void *, uint8_t *,int len), void *cbarg);
//extern int conn_process_packet(struct conn *conn, uint8_t * packet, int len,
// int (*cb) (void *, uint8_t *,int len), void *cbarg);
extern uint8_t *conn_get_message(struct conn *conn);

@ -39,6 +39,7 @@ void conn_init(struct conn * conn)
conn->wait_dtls=CAPWAP_WAIT_DTLS;
conn->wait_join=CAPWAP_WAIT_JOIN;
conn->mtu_discovery=1;
conn->remote = cw_itemstore_create();
}

@ -19,180 +19,367 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "capwap.h"
#include "dbg.h"
#include "cw_log.h"
#include "cw_util.h"
#include "conn.h"
#include "sock.h"
#include <stdio.h> //tube
#include <stdio.h> //tube
int conn_send_msg(struct conn *conn, uint8_t * rawmsg);
/**
* Init response message header
*/
void cw_init_response(struct conn *conn, uint8_t * req)
{
uint8_t *buffer = conn->resp_buffer;
int shbytes = cw_get_hdr_msg_offset(req);
int dhbytes;
memcpy(buffer, req, shbytes);
cw_set_hdr_hlen(buffer, 2);
cw_set_hdr_flags(buffer, CW_FLAG_HDR_M, 1);
dhbytes = cw_get_hdr_msg_offset(buffer);
uint8_t *msgptr = req + shbytes;
uint8_t *dmsgptr = buffer + dhbytes;
cw_set_msg_type(dmsgptr, cw_get_msg_type(msgptr) + 1);
cw_set_msg_seqnum(dmsgptr, cw_get_msg_seqnum(msgptr));
cw_set_msg_flags(dmsgptr, 0);
}
void cw_init_request(struct conn *conn, int msg_id)
{
uint8_t *buffer = conn->req_buffer;
cw_put_dword(buffer + 0, 0);
cw_put_dword(buffer + 4, 0);
cw_set_hdr_preamble(buffer, 0);
cw_set_hdr_hlen(buffer, 2);
cw_set_hdr_wbid(buffer, 1);
cw_set_hdr_rid(buffer, 0);
uint8_t *msgptr = cw_get_hdr_msg_offset(buffer) + buffer;
cw_set_msg_type(msgptr, msg_id);
cw_set_msg_flags(msgptr, 0);
cw_set_msg_elems_len(msgptr, 0);
}
static int cwrmsg_init_ctrlhdr(struct conn * conn, struct cwrmsg * cwrmsg, uint8_t * msg, int len)
/**
* send a response
*/
int cw_send_response(struct conn *conn, uint8_t * rawmsg, int len)
{
if (len<8){
cw_dbg(DBG_CW_PKT_ERR,"Discarding packet from %s, len=%d (too short)",sock_addr2str(&conn->addr),len);
cw_init_response(conn, rawmsg);
if (cw_put_msg(conn, conn->resp_buffer) == -1)
return 0;
}
conn_send_msg(conn, conn->resp_buffer);
return 1;
}
uint32_t val;
/**
* Special case error message, which is sent when an unexpected messages
* was received or somethin else happened.
* @param conn conection
* @param rawmsg the received request message, which the response belongs to
* @pqram result_code result code to send
* @return 1
*/
int cw_send_error_response(struct conn *conn, uint8_t * rawmsg, uint32_t result_code)
{
cw_init_response(conn, rawmsg);
uint8_t *out = conn->resp_buffer;
uint8_t *dst = cw_get_hdr_msg_elems_ptr(out);
int l = cw_put_elem_result_code(dst, result_code);
/* first dword of header is the message type*/
cwrmsg->type = ntohl(*((uint32_t*)(msg)));
cw_set_msg_elems_len(out + cw_get_hdr_msg_offset(out), l);
conn_send_msg(conn, conn->resp_buffer);
return 1;
}
/* second dword = seqnum, len and flags */
val = ntohl(*((uint32_t*)(msg+4)));
cwrmsg->seqnum = cw_get_dword_bits(val,0,8);
static int cw_process_msg(struct conn *conn, uint8_t * rawmsg, int len)
{
struct cw_action_in as, *af, *afm;
cwrmsg->msgelems_len=cw_get_dword_bits(val,8,16)-3;
uint8_t *msg_ptr = rawmsg + cw_get_hdr_msg_offset(rawmsg);
// ch->flags=CW_GET_DWORD_BITS(val,24,8);
cwrmsg->msgelems=msg+8;
int elems_len = cw_get_msg_elems_len(msg_ptr);
/*
if (8+elems_len != len){
cw_dbg(DBG_MSG_ERR,"Discarding message from %s, msgelems len=%d, data len=%d, (strict capwap) ",
sock_addr2str(&conn->addr),elems_len,len-8);
if (8+cwrmsg->msgelems_len != len){
if (conn_is_strict_capwap(conn)){
cw_dbg(DBG_CW_PKT_ERR,"Discarding packet from %s, msgelems len=%d, data len=%d, (strict capwap) ",
sock_addr2str(&conn->addr),cwrmsg->msgelems_len,len-8);
cw_dbg(DBG_MSG_ERR,"Discarding message from %s, msgelems len=%d, data len=%d, (strict capwap) ",
sock_addr2str(&conn->addr),elems_len,len-8);
return 0;
}
if (8+cwrmsg->msgelems_len < len){
if (8+elems_len < len){
cw_dbg(DBG_CW_RFC,"Packet from from %s has %d bytes extra data.",
sock_addr2str(&conn->addr),len-8-cwrmsg->msgelems_len);
cwrmsg->msgelems_len=len-8;
sock_addr2str(&conn->addr),len-8-elems_len);
elems_len=len-8;
}
if (8+cwrmsg->msgelems_len > len){
if (8+elems_len > len){
cw_dbg(DBG_CW_RFC,"Packet from from %s hass msgelems len of %d bytes but has only %d bytes of data, truncating.",
sock_addr2str(&conn->addr),cwrmsg->msgelems_len,len-8);
sock_addr2str(&conn->addr),elems_len,len-8);
}
return 1;
}
return 1;
}
*/
static int process_message(struct conn * conn,uint8_t *rawmsg,int rawlen,int (*cb)(void*,uint8_t *,int),void *cbarg)
{
uint8_t *msgptr = rawmsg+cw_get_hdr_msg_offset(rawmsg);
/* prepare struct for search operation */
as.capwap_state = conn->capwap_state;
as.msg_id = cw_get_msg_id(msg_ptr);
as.vendor_id = 0;
as.elem_id = 0;
as.proto = 0;
uint32_t type = cw_get_msg_type(msgptr);
/* Search for state/message combination */
afm = cw_actionlist_in_get(conn->actions->in, &as);
if (!(type & 0x1)) {
/* It's a response message, no further examination required. */
cb(cbarg,rawmsg,rawlen);
if (!afm) {
/* Throw away unexpected response messages */
if (!(as.msg_id & 1)) {
cw_dbg(DBG_MSG_ERR,
"Message type %d (%s) unexpected/illigal in %s State, discarding.",
as.msg_id, cw_strmsg(as.msg_id),
cw_strstate(conn->capwap_state));
return 0;
}
/* Request message not found in current state, check if we know
anything else about this message type */
const char *str = cw_strheap_get(conn->actions->strmsg, as.msg_id);
int result_code = 0;
if (str) {
/* Message found, but it was in wrong state */
cw_dbg(DBG_MSG_ERR,
"Message type %d (%s) not allowed in %s State.", as.msg_id,
cw_strmsg(as.msg_id), cw_strstate(as.capwap_state));
result_code = CW_RESULT_MSG_INVALID_IN_CURRENT_STATE;
} else {
/* Message is unknown */
cw_dbg(DBG_MSG_ERR, "Message type %d (%s) unknown.",
as.msg_id, cw_strmsg(as.msg_id),
cw_strstate(as.capwap_state));
result_code = CW_RESULT_MSG_UNRECOGNIZED;
}
cw_send_error_response(conn, rawmsg, result_code);
return 0;
}
/* It's a request message, check if seqnum is right and if
* we have already sent a response message*/
uint8_t seqnum = cw_get_msg_seqnum(msgptr);
/* Execute start processor for message */
if (afm->start) {
afm->start(conn, afm, rawmsg, len);
}
int s1=conn->last_seqnum_received;
int s2=seqnum;
int sd=s2-s1;
uint8_t *elems_ptr = cw_get_msg_elems_ptr(msg_ptr);
uint8_t *elem;
if ((sd>0 && sd<128) || (sd<0 && sd<-128) || s1<0){
/* seqnum is ok, normal message processing */
conn->last_seqnum_received=seqnum;
cb(cbarg,rawmsg,rawlen);
return 0;
}
/* avltree to bag the found mandatory elements */
conn->mand = intavltree_create();
if (sd != 0)
{
cw_dbg(DBG_MSG_ERR,
"Discarding message from %s, old seqnum, seqnum = %d, last seqnum=%d",
sock_addr2str(&conn->addr),s2,s1);
/* iterate through message elements */
cw_foreach_elem(elem, elems_ptr, elems_len) {
as.elem_id = cw_get_elem_id(elem);
int elem_len = cw_get_elem_len(elem);
cw_dbg_elem(conn, as.msg_id, as.elem_id, cw_get_elem_data(elem),
elem_len);
af = cw_actionlist_in_get(conn->actions->in, &as);
if (!af) {
cw_dbg(DBG_ELEM_ERR, "ELEM_ERR: Element %d (%s) not allowed in msg of type %d (%s).",
as.elem_id,cw_strelem(as.elem_id), as.msg_id, cw_strmsg(as.msg_id));
continue;
}
if (af->mand) {
/* add found mandatory message element
to mand list */
intavltree_add(conn->mand, af->item_id);
}
if (af->start) {
af->start(conn, af, cw_get_elem_data(elem), elem_len);
}
return 1;
}
/* the received request message was retransmitte by our peer,
* let's retransmit our response message if we have one*/
int result_code = 0;
if (afm->end) {
result_code = afm->end(conn, afm, rawmsg, len);
}
cw_dbg(DBG_MSG_ERR,"Retransmitted request message from %s detected, seqnum=%d, type=%d",
sock_addr2str(&conn->addr),s2,type);
/* if we've got a request message, we always have to send a response message */
if (as.msg_id & 1) {
if (result_code > 0) {
/* the end method gave us an result code, so
send an error message */
cw_send_error_response(conn, rawmsg, result_code);
} else {
/* regular response message */
cw_send_response(conn, rawmsg, len);
}
}
else{
/* whe have got a response message */
if (conn->resp_msg.type-1 != type ){
cw_dbg(DBG_MSG_ERR,"No cached response for retransmission, request seqnum=%d,in cache=%d",s2,conn->resp_msg.type );
return 0;
}
cw_dbg(DBG_MSG_ERR,"Retransmitting response message to %s, seqnum=%d",
sock_addr2str(&conn->addr),s2);
conn_send_cwmsg(conn,&conn->resp_msg);
return 1;
intavltree_destroy(conn->mand);
return result_code;
}
#ifdef WITH_CW_LOG_DEBUG
static void cw_dbg_packet(struct conn * conn, uint8_t * packet, int len)
static int process_message(struct conn *conn, uint8_t * rawmsg, int rawlen,
int (*cb) (void *, uint8_t *, int), void *cbarg)
{
if (!cw_dbg_is_level(DBG_CW_PKT_IN))
return;
uint8_t *msgptr = rawmsg + cw_get_hdr_msg_offset(rawmsg);
uint32_t type = cw_get_msg_type(msgptr);
if (!(type & 0x1)) {
/* It's a response message, no further examination required. */
// cb(cbarg, rawmsg, rawlen);
return cw_process_msg(conn,rawmsg,rawlen);
}
/* It's a request message, check if seqnum is right and if
* we have already sent a response message*/
/* print the header */
char hdr[200];
hdr_print(hdr,packet,len);
uint8_t seqnum = cw_get_msg_seqnum(msgptr);
int s1 = conn->last_seqnum_received;
int s2 = seqnum;
int sd = s2 - s1;
if (!cw_dbg_is_level(DBG_CW_PKT_DMP)){
cw_dbg(DBG_CW_PKT_IN,"Processing capwap packet from %s, len=%d\n%s",sock_addr2str(&conn->addr),len,hdr);
return;
if ((sd >