From c43f85b2a66e7eb3b90a85ed6cea3b6e82138eb0 Mon Sep 17 00:00:00 2001 From: "7u83@mail.ru" <7u83@mail.ru@noemail.net> Date: Fri, 10 Apr 2015 15:14:55 +0000 Subject: [PATCH] More work on CW VM code .. FossilOrigin-Name: 3b0cb324535527b32d0e938b03151c75f6100ca2059fc121e2c4d350a8caf8a4 --- src/ac/Makefile | 2 +- src/ac/ac_global.c | 2 +- src/ac/ac_main.c | 22 + src/ac/wtpman.c | 13 +- src/capwap/Doxyfile | 2 +- src/capwap/Makefile | 28 +- src/capwap/aciplist.c | 5 + src/capwap/aciplist.h | 4 +- src/capwap/avltree.h | 60 ++- src/capwap/avltree_foreach_from_lr.c | 3 + src/capwap/capwap.h | 56 ++- src/capwap/capwap_80211.h | 29 +- src/capwap/capwap_action_helpers.c | 19 +- src/capwap/capwap_actions.h | 29 +- src/capwap/capwap_actions_ac.c | 12 +- src/capwap/capwap_actions_wtp.c | 61 ++- src/capwap/capwap_items.h | 8 +- src/capwap/capwap_strings_elem.c | 2 +- src/capwap/capwap_strings_item.c | 2 +- src/capwap/capwap_strings_msg.c | 2 +- src/capwap/capwap_strings_state.c | 2 +- src/capwap/capwap_strings_vendor.c | 3 +- src/capwap/conn.h | 12 +- src/capwap/conn_init.c | 1 + src/capwap/conn_process_packet.c | 439 +++++++++++++----- src/capwap/cw_check_missing_mand.c | 42 +- src/capwap/cw_in_check_disc_req.c | 5 + src/capwap/cw_in_check_disc_resp.c | 17 +- src/capwap/cw_in_check_img_data_req.c | 11 +- src/capwap/cw_in_check_join_req.c | 4 +- src/capwap/cw_in_cisco_image_identifier.c | 2 +- src/capwap/cw_in_generic.c | 34 +- src/capwap/cw_in_wtp_board_data.c | 2 +- src/capwap/cw_in_wtp_descriptor.c | 2 +- src/capwap/cw_log.h | 4 + src/capwap/cw_log_debug.c | 104 +---- src/capwap/cw_out_ac_descriptor.c | 6 +- .../cw_out_capwap_control_ip_addr_list.c | 4 +- src/capwap/cw_out_cisco_ac_descriptor.c | 4 +- src/capwap/cw_out_generic.c | 44 +- src/capwap/cw_out_wtp_board_data.c | 92 ++-- src/capwap/cw_process_msg.c | 2 +- src/capwap/cw_strlist_get_str.c | 2 +- src/capwap/cw_util.h | 6 +- src/capwap/dbg.c | 51 +- src/capwap/dbg.h | 21 +- src/capwap/dtls_gnutls.c | 12 +- src/capwap/dtls_gnutls.h | 1 + src/capwap/dtls_gnutls_accept.c | 2 +- src/capwap/dtls_gnutls_bio.c | 2 +- src/capwap/format.h | 1 + src/capwap/intavltree.h | 1 + src/capwap/itemstore.c | 9 +- src/capwap/itemstore.h | 36 +- src/capwap/strheap.h | 4 +- src/wtp/Makefile | 2 +- src/wtp/discovery.c | 158 +++++-- src/wtp/join.c | 123 +++++ src/wtp/wtp_main.c | 19 +- 59 files changed, 1188 insertions(+), 459 deletions(-) diff --git a/src/ac/Makefile b/src/ac/Makefile index 030b303f..37cc665e 100644 --- a/src/ac/Makefile +++ b/src/ac/Makefile @@ -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 diff --git a/src/ac/ac_global.c b/src/ac/ac_global.c index 17b97f1b..2b931f83 100644 --- a/src/ac/ac_global.c +++ b/src/ac/ac_global.c @@ -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; } diff --git a/src/ac/ac_main.c b/src/ac/ac_main.c index 3f76e626..5ec04065 100644 --- a/src/ac/ac_main.c +++ b/src/ac/ac_main.c @@ -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"); diff --git a/src/ac/wtpman.c b/src/ac/wtpman.c index 08a9af9b..f415d2ae 100644 --- a/src/ac/wtpman.c +++ b/src/ac/wtpman.c @@ -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) { diff --git a/src/capwap/Doxyfile b/src/capwap/Doxyfile index 00983c42..04a16f70 100644 --- a/src/capwap/Doxyfile +++ b/src/capwap/Doxyfile @@ -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. diff --git a/src/capwap/Makefile b/src/capwap/Makefile index ed2b2baa..faa925c5 100644 --- a/src/capwap/Makefile +++ b/src/capwap/Makefile @@ -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) \ diff --git a/src/capwap/aciplist.c b/src/capwap/aciplist.c index 1fdf6f52..45bb65fd 100644 --- a/src/capwap/aciplist.c +++ b/src/capwap/aciplist.c @@ -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) diff --git a/src/capwap/aciplist.h b/src/capwap/aciplist.h index 88168547..a92e5261 100644 --- a/src/capwap/aciplist.h +++ b/src/capwap/aciplist.h @@ -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 diff --git a/src/capwap/avltree.h b/src/capwap/avltree.h index ebfbcc18..68dab140 100644 --- a/src/capwap/avltree.h +++ b/src/capwap/avltree.h @@ -30,8 +30,15 @@ #include +/** 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,8 +169,24 @@ 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 diff --git a/src/capwap/avltree_foreach_from_lr.c b/src/capwap/avltree_foreach_from_lr.c index e34d567b..f5d4cb22 100644 --- a/src/capwap/avltree_foreach_from_lr.c +++ b/src/capwap/avltree_foreach_from_lr.c @@ -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) diff --git a/src/capwap/capwap.h b/src/capwap/capwap.h index 863df83d..0ab861b8 100644 --- a/src/capwap/capwap.h +++ b/src/capwap/capwap.h @@ -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 diff --git a/src/capwap/capwap_80211.h b/src/capwap/capwap_80211.h index 8155e3b0..baa7e0c9 100644 --- a/src/capwap/capwap_80211.h +++ b/src/capwap/capwap_80211.h @@ -1,4 +1,11 @@ +#ifndef __CAPWAP_80211 +#define __CAPWAP_80211 +#include "capwap.h" +#include + +#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 diff --git a/src/capwap/capwap_action_helpers.c b/src/capwap/capwap_action_helpers.c index 1bfc9fe4..5eef1d5f 100644 --- a/src/capwap/capwap_action_helpers.c +++ b/src/capwap/capwap_action_helpers.c @@ -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_outgoing(struct conn *conn, struct cw_action_out *a) +{ + return cw_itemstore_get(conn->outgoing, a->item_id); +} + +struct cw_item *cw_out_get_incomming(struct conn *conn, struct cw_action_out *a) +{ + 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); + return cw_itemstore_get(conn->local,a->item_id); } -struct cw_item *cw_out_get_remote(struct conn *conn, struct cw_action_out *a) -{ - return cw_itemstore_get(conn->local, a->item_id); -} - - diff --git a/src/capwap/capwap_actions.h b/src/capwap/capwap_actions.h index fa7727ac..5d5a3ce2 100644 --- a/src/capwap/capwap_actions.h +++ b/src/capwap/capwap_actions.h @@ -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 diff --git a/src/capwap/capwap_actions_ac.c b/src/capwap/capwap_actions_ac.c index d7ebfa78..11941ddd 100644 --- a/src/capwap/capwap_actions_ac.c +++ b/src/capwap/capwap_actions_ac.c @@ -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} , diff --git a/src/capwap/capwap_actions_wtp.c b/src/capwap/capwap_actions_wtp.c index 739c6259..2c42c8d6 100644 --- a/src/capwap/capwap_actions_wtp.c +++ b/src/capwap/capwap_actions_wtp.c @@ -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: Vendor Specific */ + /* Element CAPWAP Control IPv4 Address */ {0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_RESPONSE, - CW_ACTION_IN_VENDOR_SPECIFIC_PAYLOAD, 1} + CW_ACTION_IN_CAPWAP_CONTROL_IPV4_ADDRESS, 1} , - /* Element CAPWAP Control IPv4 Address */ - + + /* Element: Vendor Specific */ + {0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_RESPONSE, + CW_ACTION_IN_VENDOR_SPECIFIC_PAYLOAD, 0} + , + + + /* ------------------------------------------------------------------------------- */ + + /* 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} diff --git a/src/capwap/capwap_items.h b/src/capwap/capwap_items.h index 43743c0e..906b2a6a 100644 --- a/src/capwap/capwap_items.h +++ b/src/capwap/capwap_items.h @@ -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 */ }; diff --git a/src/capwap/capwap_strings_elem.c b/src/capwap/capwap_strings_elem.c index 434e2e49..328504e4 100644 --- a/src/capwap/capwap_strings_elem.c +++ b/src/capwap/capwap_strings_elem.c @@ -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"} }; diff --git a/src/capwap/capwap_strings_item.c b/src/capwap/capwap_strings_item.c index 14f384f7..e70e2a39 100644 --- a/src/capwap/capwap_strings_item.c +++ b/src/capwap/capwap_strings_item.c @@ -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"} } diff --git a/src/capwap/capwap_strings_msg.c b/src/capwap/capwap_strings_msg.c index f9d4826d..de06c061 100644 --- a/src/capwap/capwap_strings_msg.c +++ b/src/capwap/capwap_strings_msg.c @@ -30,7 +30,7 @@ struct cw_str capwap_strings_msg[] = { Station Configuration Response 26 */ -{0,"Unknown Message Type"} +{CW_STR_STOP,"Unknown Message Type"} }; diff --git a/src/capwap/capwap_strings_state.c b/src/capwap/capwap_strings_state.c index 2df07447..51f8ca42 100644 --- a/src/capwap/capwap_strings_state.c +++ b/src/capwap/capwap_strings_state.c @@ -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" } }; diff --git a/src/capwap/capwap_strings_vendor.c b/src/capwap/capwap_strings_vendor.c index 565be546..e4f43e1b 100644 --- a/src/capwap/capwap_strings_vendor.c +++ b/src/capwap/capwap_strings_vendor.c @@ -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" } }; diff --git a/src/capwap/conn.h b/src/capwap/conn.h index 02514b55..05a60a3b 100644 --- a/src/capwap/conn.h +++ b/src/capwap/conn.h @@ -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); diff --git a/src/capwap/conn_init.c b/src/capwap/conn_init.c index 35d89cca..a701bea8 100644 --- a/src/capwap/conn_init.c +++ b/src/capwap/conn_init.c @@ -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(); } diff --git a/src/capwap/conn_process_packet.c b/src/capwap/conn_process_packet.c index 53a7aaba..8e7d7e60 100644 --- a/src/capwap/conn_process_packet.c +++ b/src/capwap/conn_process_packet.c @@ -19,72 +19,274 @@ #include #include +#include #include "capwap.h" +#include "dbg.h" + #include "cw_log.h" #include "cw_util.h" #include "conn.h" #include "sock.h" -#include //tube +#include //tube -static int cwrmsg_init_ctrlhdr(struct conn * conn, struct cwrmsg * cwrmsg, uint8_t * msg, int len) + + + + + + +int conn_send_msg(struct conn *conn, uint8_t * rawmsg); + + + + +/** + * Init response message header + */ +void cw_init_response(struct conn *conn, uint8_t * req) { - if (len<8){ - cw_dbg(DBG_CW_PKT_ERR,"Discarding packet from %s, len=%d (too short)",sock_addr2str(&conn->addr),len); + 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); + + +} + +/** + * send a response + */ +int cw_send_response(struct conn *conn, uint8_t * rawmsg, int 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; - /* first dword of header is the message type*/ - cwrmsg->type = ntohl(*((uint32_t*)(msg))); - /* second dword = seqnum, len and flags */ - val = ntohl(*((uint32_t*)(msg+4))); - cwrmsg->seqnum = cw_get_dword_bits(val,0,8); +/** + * 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); - cwrmsg->msgelems_len=cw_get_dword_bits(val,8,16)-3; + uint8_t *out = conn->resp_buffer; -// ch->flags=CW_GET_DWORD_BITS(val,24,8); - cwrmsg->msgelems=msg+8; + uint8_t *dst = cw_get_hdr_msg_elems_ptr(out); + int l = cw_put_elem_result_code(dst, result_code); + + cw_set_msg_elems_len(out + cw_get_hdr_msg_offset(out), l); + + conn_send_msg(conn, conn->resp_buffer); + + return 1; +} + + +static int cw_process_msg(struct conn *conn, uint8_t * rawmsg, int len) +{ + struct cw_action_in as, *af, *afm; + + uint8_t *msg_ptr = rawmsg + cw_get_hdr_msg_offset(rawmsg); + + 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; + +*/ + + + /* 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; + + + /* Search for state/message combination */ + afm = cw_actionlist_in_get(conn->actions->in, &as); + + 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; + } + + + /* Execute start processor for message */ + if (afm->start) { + afm->start(conn, afm, rawmsg, len); + } + + uint8_t *elems_ptr = cw_get_msg_elems_ptr(msg_ptr); + uint8_t *elem; + + /* avltree to bag the found mandatory elements */ + conn->mand = intavltree_create(); + + /* 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); + } + + } + + int result_code = 0; + if (afm->end) { + result_code = afm->end(conn, afm, rawmsg, len); + } + + /* 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 */ + + + } + + intavltree_destroy(conn->mand); + + return result_code; } -static int process_message(struct conn * conn,uint8_t *rawmsg,int rawlen,int (*cb)(void*,uint8_t *,int),void *cbarg) + + + + + + +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); + 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 0; + // cb(cbarg, rawmsg, rawlen); + return cw_process_msg(conn,rawmsg,rawlen); } /* It's a request message, check if seqnum is right and if @@ -92,107 +294,92 @@ static int process_message(struct conn * conn,uint8_t *rawmsg,int rawlen,int (*c uint8_t seqnum = cw_get_msg_seqnum(msgptr); - int s1=conn->last_seqnum_received; - int s2=seqnum; - int sd=s2-s1; + int s1 = conn->last_seqnum_received; + int s2 = seqnum; + int sd = s2 - s1; - if ((sd>0 && sd<128) || (sd<0 && sd<-128) || s1<0){ + 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; + conn->last_seqnum_received = seqnum; + return cw_process_msg(conn,rawmsg,rawlen); + //cb(cbarg, rawmsg, rawlen); + //return 0; } - if (sd != 0) - { + 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); - - return 1; + "Discarding message from %s, old seqnum, seqnum = %d, last seqnum=%d", + sock_addr2str(&conn->addr), s2, s1); + errno = EAGAIN; + return -1; } - /* the received request message was retransmitte by our peer, + /* the received request message was retransmittet by our peer, * let's retransmit our response message if we have one*/ - cw_dbg(DBG_MSG_ERR,"Retransmitted request message from %s detected, seqnum=%d, type=%d", - sock_addr2str(&conn->addr),s2,type); + cw_dbg(DBG_MSG_ERR, + "Retransmitted request message from %s detected, seqnum=%d, type=%d", + sock_addr2str(&conn->addr), s2, type); - 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; + + if (cw_get_hdr_msg_type(conn->resp_buffer) - 1 != type) { + cw_dbg(DBG_MSG_ERR, + "No cached response for retransmission, request seqnum=%d,in cache=%d", + s2, conn->resp_msg.type); + errno = EAGAIN; + return -1; } - 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; + cw_dbg(DBG_MSG_ERR, "Retransmitting response message to %s, seqnum=%d", + sock_addr2str(&conn->addr), s2); +// conn_send_cwmsg(conn, &conn->resp_msg); + errno = EAGAIN; + return -1; } -#ifdef WITH_CW_LOG_DEBUG -static void cw_dbg_packet(struct conn * conn, uint8_t * packet, int len) -{ - if (!cw_dbg_is_level(DBG_CW_PKT_IN)) - return; +//int conn_process_packet(struct conn *conn, uint8_t * packet, int len, +// int (*cb) (void *, uint8_t *, int), void *cbarg) - - /* print the header */ - char hdr[200]; - hdr_print(hdr,packet,len); - - - 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; - - } - - cw_dbg_dmp(DBG_CW_PKT_DMP,packet,len,"Processing packet from %s, len=%d\n%s\n\tDump:", - sock_addr2str(&conn->addr),len,hdr - ); - - -} - -#else - #define cw_dbg_packet(...) -#endif - - -int conn_process_packet(struct conn * conn, uint8_t *packet, int len,int (*cb)(void*,uint8_t *,int),void *cbarg) +int conn_process_packet(struct conn *conn, uint8_t * packet, int len) { - if (len<8){ + if (len < 8) { /* packet too short */ - cw_dbg(DBG_CW_PKT_ERR,"Discarding packet from %s, packet too short, len=%d",sock_addr2str(&conn->addr),len); + cw_dbg(DBG_CW_PKT_ERR, + "Discarding packet from %s, packet too short, len=%d", + sock_addr2str(&conn->addr), len); return 0; } int preamble = cw_get_hdr_preamble(packet); - if ( (preamble & 0xf0) != CW_VERSION){ + if ((preamble & 0xf0) != CW_VERSION) { /* wrong version */ - cw_dbg(DBG_CW_PKT_ERR,"Discarding packet from %s, wrong version, version=%d",sock_addr2str(&conn->addr),(preamble&0xf0)>>8); + cw_dbg(DBG_CW_PKT_ERR, + "Discarding packet from %s, wrong version, version=%d", + sock_addr2str(&conn->addr), (preamble & 0xf0) >> 8); return 0; } - if (preamble & 0xf ) { + if (preamble & 0xf) { /* decode dtls */ return 0; } /* log this packet */ - cw_dbg_packet(conn,packet,len); + cw_dbg_packet(conn, packet, len); - int offs = cw_get_hdr_msg_offset(packet); - + int offs = cw_get_hdr_msg_offset(packet); + int payloadlen = len - offs; - if (payloadlen<0){ - cw_dbg(DBG_CW_PKT_ERR,"Discarding packet from %s, header length greater than len, hlen=%d",sock_addr2str(&conn->addr),offs); + if (payloadlen < 0) { + cw_dbg(DBG_CW_PKT_ERR, + "Discarding packet from %s, header length greater than len, hlen=%d", + sock_addr2str(&conn->addr), offs); /* EINVAL */ return 0; } @@ -206,31 +393,33 @@ int conn_process_packet(struct conn * conn, uint8_t *packet, int len,int (*cb)(v //printf ("Offs is %d RML is %d\n",offs,cw_get_hdr_rmac_len(packet)); /* Check Radio MAC if preset */ - if (cw_get_hdr_flag_m(packet)){ - - if (cw_get_hdr_rmac_len(packet)+8>offs){ + if (cw_get_hdr_flag_m(packet)) { + + if (cw_get_hdr_rmac_len(packet) + 8 > offs) { /* wrong rmac size */ - cw_dbg(DBG_CW_PKT_ERR,"Discarding packet, wrong R-MAC size, size=%d",*(packet+8)); + cw_dbg(DBG_CW_PKT_ERR, + "Discarding packet, wrong R-MAC size, size=%d", + *(packet + 8)); return 0; } -// memcpy(cwrmsg.rmac, packet+8,8); +// memcpy(cwrmsg.rmac, packet+8,8); } -// else{ -// cwrmsg.rmac[0]=0; -// } +// else{ +// cwrmsg.rmac[0]=0; +// } - if (cw_get_hdr_flag_f(packet)){ /* fragmented */ - uint8_t * f; - f = fragman_add(conn->fragman, packet,offs,payloadlen); - if (f==NULL) + if (cw_get_hdr_flag_f(packet)) { /* fragmented */ + uint8_t *f; + f = fragman_add(conn->fragman, packet, offs, payloadlen); + if (f == NULL) return 0; - cw_dbg_packet(conn,f+4,*(uint32_t*)f); + cw_dbg_packet(conn, f + 4, *(uint32_t *) f); - - // extern int cw_process_msg(struct conn * conn,uint8_t*msg,int len); - // cw_process_msg(conn,f+4,*(uint32_t*)f); + + // extern int cw_process_msg(struct conn * conn,uint8_t*msg,int len); + // cw_process_msg(conn,f+4,*(uint32_t*)f); //printf("Received a fragmented packetm should process it"); //exit(0); @@ -241,43 +430,43 @@ int conn_process_packet(struct conn * conn, uint8_t *packet, int len,int (*cb)(v return; }; */ - process_message(conn,f+4,*(uint32_t*)f,cb,cbarg); + int rc = process_message(conn, f + 4, *(uint32_t *) f, NULL, NULL); - free (f); - return 1; + free(f); + return rc; } - //extern int cw_process_msg(struct conn * conn,uint8_t*msg,int len); //cw_process_msg(conn,packet,len); //if (!cwrmsg_init_ctrlhdr(conn,&cwrmsg,packet+hlen,len-hlen) ){ - // cw_dbg(DBG_CW_PKT_ERR,"Discarding packet from %s, len=%d (too short)",sock_addr2str(&conn->addr)); - // return; + // cw_dbg(DBG_CW_PKT_ERR,"Discarding packet from %s, len=%d (too short)",sock_addr2str(&conn->addr)); + // return; //} //msg_4*((val >> 19) & 0x1f); - process_message(conn,packet,len,cb,cbarg); - return 1; + return process_message(conn, packet, len, NULL,NULL); } /** * Used as main message loop - */ + */ int cw_read_messages(struct conn *conn) { - uint8_t buf[2024]; - int len = 2024; + uint8_t buf[2024]; + int len = 2024; - int n = conn->read(conn, buf, len); - if (n<0 ) + int n = conn->read(conn, buf, len); + if (n < 0) return n; - - if (n > 0) - conn_process_packet(conn, buf, n, cw_process_msg, conn); - + if (n > 0) { + printf("Have a packet with %d bytes\n",n); + return conn_process_packet(conn, buf, n); + } + //printf("DTLS_ERROR: %d\n",conn->dtls_error); + errno = EAGAIN; + return -1; + } - - diff --git a/src/capwap/cw_check_missing_mand.c b/src/capwap/cw_check_missing_mand.c index 96323e4a..fbefdc7e 100644 --- a/src/capwap/cw_check_missing_mand.c +++ b/src/capwap/cw_check_missing_mand.c @@ -12,15 +12,26 @@ struct args { static int check_mand_cb(void *priv, void *val) { + cw_action_in_t *a = (cw_action_in_t*)val; struct args *args = (struct args*) priv; +printf("Na?\n"); +return 1; + if ( (args->a->msg_id != a->msg_id) || (args->a->capwap_state != a->capwap_state)) + { + printf ("Was soll das denn?\n"); + printf("End of fun\n"); + return 0; + } +printf("Nu?\n"); +return 1; -// printf("Found wat %d %d %c\n",a->msg_id,a->elem_id, a->mand ? '*':' '); + printf("Found wat %d %d %c\n",a->msg_id,a->elem_id, a->mand ? '*':'-'); if (a->mand) { int i = a->item_id; void * rc = avltree_del(args->mand,&i); @@ -40,6 +51,8 @@ static int check_mand_cb(void *priv, void *val) int cw_check_missing_mand(cw_action_in_t ** out, struct conn * conn, cw_action_in_t *a) { + + cw_action_in_t as; as.capwap_state = a->capwap_state; @@ -48,6 +61,29 @@ int cw_check_missing_mand(cw_action_in_t ** out, struct conn * conn, cw_action_i as.elem_id = 0; as.proto=0; + + DEFINE_AVLITER(it,conn->actions->in); + int n=0; + avliter_foreach_from(&it,&as) { + cw_action_in_t * a = avliter_get(&it); + if (a->msg_id != as.msg_id) + break; + if (!a->mand) + continue; + + int i = a->item_id; + void * rc = avltree_del(conn->mand,&i); + if (!rc) { + out[n++]=a; + } + + } + + + + +/* + struct args args; args.a = &as; args.mand=conn->mand; @@ -55,8 +91,8 @@ int cw_check_missing_mand(cw_action_in_t ** out, struct conn * conn, cw_action_i args.n=0; avltree_foreach_from_asc(conn->actions->in,&as,check_mand_cb,&args); - - return args.n; +*/ + return n; } diff --git a/src/capwap/cw_in_check_disc_req.c b/src/capwap/cw_in_check_disc_req.c index dc0566a3..4c5d8a92 100644 --- a/src/capwap/cw_in_check_disc_req.c +++ b/src/capwap/cw_in_check_disc_req.c @@ -1,5 +1,7 @@ #include "capwap.h" +#include "capwap_items.h" + #include "intavltree.h" #include "cw_log.h" #include "dbg.h" @@ -24,6 +26,9 @@ int cw_in_check_disc_req(struct conn *conn, struct cw_action_in *a, uint8_t * da return -1; } + + /* ok, send response */ + return 0; } diff --git a/src/capwap/cw_in_check_disc_resp.c b/src/capwap/cw_in_check_disc_resp.c index bf6f2a23..4583bdb2 100644 --- a/src/capwap/cw_in_check_disc_resp.c +++ b/src/capwap/cw_in_check_disc_resp.c @@ -1,5 +1,6 @@ #include "capwap.h" +#include "capwap_items.h" #include "intavltree.h" #include "cw_log.h" #include "dbg.h" @@ -12,7 +13,7 @@ int cw_in_check_disc_resp(struct conn *conn, struct cw_action_in *a, uint8_t * d int n = cw_check_missing_mand(mlist, conn, a); cw_dbg_missing_mand(DBG_ELEM, conn, mlist, n, a); - cw_dbg(DBG_CW_INFO,"This response came from: %s\n",sock_addr2str(conn->addr)); + cw_dbg(DBG_CW_INFO,"This response came from: %s\n",sock_addr2str(&conn->addr)); /* if mandatory elements are missing, ignore this response */ @@ -23,10 +24,20 @@ int cw_in_check_disc_resp(struct conn *conn, struct cw_action_in *a, uint8_t * d return -1; } + /* we have all AC information in the incomming buffer */ + cw_itemstore_t discs; - + discs = cw_itemstore_get_avltree_c(conn->remote, CW_ITEM_DISCOVERIES, + cw_itemstore_create); + + if ( !discs ) { + cw_log(LOG_ERR,"Can't allocate store for disc resp"); + return 0; + } + + cw_itemstore_set_avltree(discs,discs->count,conn->incomming); + conn->incomming = cw_itemstore_create(); - /* ok, send response */ return 0; } diff --git a/src/capwap/cw_in_check_img_data_req.c b/src/capwap/cw_in_check_img_data_req.c index dfaaa24a..42b1254a 100644 --- a/src/capwap/cw_in_check_img_data_req.c +++ b/src/capwap/cw_in_check_img_data_req.c @@ -20,11 +20,12 @@ int cw_in_check_img_data_req(struct conn *conn, struct cw_action_in *a, uint8_t } - struct cw_item *i = cw_itemstore_get(conn->remote,CW_ITEM_IMAGE_IDENTIFIER); + struct cw_item *i = cw_itemstore_get(conn->incomming,CW_ITEM_IMAGE_IDENTIFIER); if (i) { uint32_t vendor_id = vendorstr_get_vendor_id(i->data); - const char * image_dir = cw_itemstore_get_str(conn->local,CW_ITEM_AC_IMAGE_DIR); + const char * image_dir; + //XXX image_dir = cw_itemstore_get_str(conn->local,CW_ITEM_AC_IMAGE_DIR); char * image_filename = malloc(6+vendorstr_len(i->data)+1+strlen(image_dir)); if (!image_filename) @@ -41,9 +42,7 @@ int cw_in_check_img_data_req(struct conn *conn, struct cw_action_in *a, uint8_t return CW_RESULT_IMAGE_DATA_OTHER_ERROR; } - cw_itemstore_set_str(conn->remote,CW_ITEM_WTP_IMAGE_FILENAME,image_filename); - - + cw_itemstore_set_str(conn->outgoing,CW_ITEM_WTP_IMAGE_FILENAME,image_filename); } @@ -52,7 +51,7 @@ int cw_in_check_img_data_req(struct conn *conn, struct cw_action_in *a, uint8_t // cw_itemstore_set_dword(conn->local,CW_ITEM_RESULT_CODE,0); // conn->capwap_state = CW_STATE_CONFIGURE; - cw_itemstore_set_dword(conn->local,CW_ITEM_RESULT_CODE,0); + cw_itemstore_set_dword(conn->outgoing,CW_ITEM_RESULT_CODE,0); conn->capwap_state=CW_STATE_IMAGE_DATA; return 0; diff --git a/src/capwap/cw_in_check_join_req.c b/src/capwap/cw_in_check_join_req.c index 2c86e8b4..2315ccb8 100644 --- a/src/capwap/cw_in_check_join_req.c +++ b/src/capwap/cw_in_check_join_req.c @@ -9,6 +9,8 @@ int cw_in_check_join_req(struct conn *conn, struct cw_action_in *a, uint8_t * da int len) { + printf("join req checker\n"); + cw_action_in_t * mlist[60]; /* Check for mandatory elements */ @@ -21,7 +23,7 @@ int cw_in_check_join_req(struct conn *conn, struct cw_action_in *a, uint8_t * da /* set result code to ok and change to configure state */ - cw_itemstore_set_dword(conn->local,CW_ITEM_RESULT_CODE,0); + cw_itemstore_set_dword(conn->outgoing,CW_ITEM_RESULT_CODE,0); conn->capwap_state = CW_STATE_CONFIGURE; return 0; diff --git a/src/capwap/cw_in_cisco_image_identifier.c b/src/capwap/cw_in_cisco_image_identifier.c index 2d1feea7..67a449a7 100644 --- a/src/capwap/cw_in_cisco_image_identifier.c +++ b/src/capwap/cw_in_cisco_image_identifier.c @@ -29,7 +29,7 @@ int cw_in_cisco_image_identifier(struct conn *conn,struct cw_action_in * a,uint8 } // cw_itemstore_set(conn->remote,a->item_id,a->itemtype,data+dstart,len); - cw_itemstore_set_vendorstr(conn->remote,a->item_id,vendor_id,data+dstart,len); + cw_itemstore_set_vendorstr(conn->incomming,a->item_id,vendor_id,data+dstart,len); return 1; } diff --git a/src/capwap/cw_in_generic.c b/src/capwap/cw_in_generic.c index ea2fcdab..fd2fdd37 100644 --- a/src/capwap/cw_in_generic.c +++ b/src/capwap/cw_in_generic.c @@ -17,8 +17,40 @@ int cw_in_generic(struct conn *conn,struct cw_action_in * a,uint8_t *data,int le return 0; } + + cw_itemstore_t itemstore = conn->incomming; - cw_itemstore_set(conn->remote,a->item_id,a->itemtype,data,len); + switch (a->itemtype) { + case CW_ITEMTYPE_BYTE: + cw_itemstore_set_byte(itemstore,a->item_id,*data); + break; + case CW_ITEMTYPE_WORD: + cw_itemstore_set_word(itemstore,a->item_id,cw_get_word(data)); + break; + case CW_ITEMTYPE_DWORD: + cw_itemstore_set_dword(itemstore,a->item_id,cw_get_dword(data)); + break; + case CW_ITEMTYPE_STR: + cw_itemstore_set_strn(itemstore,a->item_id,(char*)data,len); + break; + case CW_ITEMTYPE_BSTR: + cw_itemstore_set_bstrn(itemstore,a->item_id,data,len); + break; + case CW_ITEMTYPE_DATA: + cw_itemstore_set_data(itemstore,a->item_id,data,len); + break; + case CW_ITEMTYPE_VENDORSTR: + cw_itemstore_set_vendorstr(itemstore,a->item_id, + cw_get_dword(data),data+4,len-4); + + + } + + + +//int src = cw_itemstore_set(conn->incomming,a->item_id,a->itemtype,data,len); + +//printf("Cunint ic: %d %d\n",src,conn->incomming->count); return 0; } diff --git a/src/capwap/cw_in_wtp_board_data.c b/src/capwap/cw_in_wtp_board_data.c index ece5fdd6..acec612e 100644 --- a/src/capwap/cw_in_wtp_board_data.c +++ b/src/capwap/cw_in_wtp_board_data.c @@ -96,7 +96,7 @@ int cw_in_wtp_board_data(struct conn *conn, struct cw_action_in *a, uint8_t * da return 1; } - cw_itemstore_t itemstore = conn->remote; + cw_itemstore_t itemstore = conn->incomming; cw_itemstore_set_dword(itemstore, CW_ITEM_WTP_BOARD_VENDOR,cw_get_dword(data)); readsubelems_wtp_board_data(itemstore,data+4,len-4); diff --git a/src/capwap/cw_in_wtp_descriptor.c b/src/capwap/cw_in_wtp_descriptor.c index 0636d076..af191a81 100644 --- a/src/capwap/cw_in_wtp_descriptor.c +++ b/src/capwap/cw_in_wtp_descriptor.c @@ -34,7 +34,7 @@ static int readelem_wtp_descriptor(struct conn *conn, struct cw_action_in *a, ui if (len<6) return -1; - cw_itemstore_t itemstore = conn->remote; + cw_itemstore_t itemstore = conn->incomming; cw_itemstore_set_byte(itemstore,CW_ITEM_WTP_MAX_RADIOS,cw_get_byte(data)); cw_itemstore_set_byte(itemstore,CW_ITEM_WTP_RADIOS_IN_USE,cw_get_byte(data+1)); diff --git a/src/capwap/cw_log.h b/src/capwap/cw_log.h index 4d2edf00..f389a0d6 100644 --- a/src/capwap/cw_log.h +++ b/src/capwap/cw_log.h @@ -28,6 +28,10 @@ #include #include +#ifndef LOG_ERROR +#define LOG_ERROR LOG_ERR +#endif + /** * @defgroup DebugOptions Dbug Options * @{ diff --git a/src/capwap/cw_log_debug.c b/src/capwap/cw_log_debug.c index 59d778cc..05135ea0 100644 --- a/src/capwap/cw_log_debug.c +++ b/src/capwap/cw_log_debug.c @@ -43,94 +43,6 @@ int cw_dbg_opt_level = 0; int cw_log_debug_level = 0; - - -static void cw_log_debug0_(const char *format, ...) -{ - if (cw_log_debug_level < 0) - return; - va_list args; - va_start(args, format); - cw_vlog_(LOG_DEBUG, format, args); - va_end(args); - closelog(); -} - -static void cw_log_debug1_(const char *format, ...) -{ - if (cw_log_debug_level < 1) - return; - - va_list args; - va_start(args, format); - cw_vlog_(LOG_DEBUG, format, args); - va_end(args); - closelog(); -} - - -static void cw_log_debug2_(const char *format, ...) -{ - if (cw_log_debug_level < 2) - return; - va_list args; - va_start(args, format); - cw_vlog_(LOG_DEBUG, format, args); - va_end(args); - closelog(); -} - - - - -int cw_log_debug_dump_(int level, const uint8_t * data, int len, const char *format, ...) -{ - int maxtlen = 2048; - int i; - int rowlen = CW_LOG_DUMP_ROW_LEN; - int rows = len / rowlen; - int tlen = 0; - - char *dst = malloc(len * 3 + (rows * 2) + 8 + maxtlen); - if (!dst) - return 0; - - if (format != NULL) { - va_list args; - va_start(args, format); - tlen = vsnprintf(dst, maxtlen, format, args); - va_end(args); - } - - - - if (len % CW_LOG_DUMP_ROW_LEN) - rows++; - - - - char *pdst = dst + tlen; - sprintf(pdst, "\n\t"); - pdst += 2; - - for (i = 0; i < len; i++) { - sprintf(pdst, "%02X ", data[i] & 0xff); - pdst += 3; - if ((i + 1) % rowlen == 0) { - sprintf(pdst, "\n\t"); - pdst += 2; - } - - } - - cw_log_debug_cbs[level] ("%s", dst); - - free(dst); - return 1; - -} - - void cw_log_dbg_(int level, const char *file, int line, const char *format, ...) { @@ -248,8 +160,8 @@ void cw_log_dbg_dmp_(int level, const char *file, int line, -void (*cw_log_debug_cbs[]) (const char *fromat, ...) = { -cw_log_debug0_, cw_log_debug1_, cw_log_debug2_}; +//void (*cw_log_debug_cbs[]) (const char *fromat, ...) = { +//cw_log_debug0_, cw_log_debug1_, cw_log_debug2_}; @@ -361,16 +273,4 @@ void lw_dbg_elem_(int msg_id, int elem_id, const uint8_t * elem_data, int elem_l } -/* -void cw_dbg_missing_mand_elems_(struct conn *conn, int msgtype, int *mand) -{ - if (!cw_dbg_is_level(DBG_CW_RFC)) - return; - if (cw_is_missing_mand_elems(mand)) { - char str[512]; - cw_get_missing_mand_elems(str, mand); - cw_dbg(DBG_CW_RFC, "Missing msgelems in %s: %s", cw_strmsg(msgtype), str); - } -} -*/ diff --git a/src/capwap/cw_out_ac_descriptor.c b/src/capwap/cw_out_ac_descriptor.c index 875a989a..f14b1ec5 100644 --- a/src/capwap/cw_out_ac_descriptor.c +++ b/src/capwap/cw_out_ac_descriptor.c @@ -24,7 +24,7 @@ int cw_out_ac_descriptor(struct conn *conn,struct cw_action_out * a,uint8_t *dst uint8_t *d = dst+4; struct cw_item * i; - i = cw_itemstore_get(conn->local,CW_ITEM_AC_STATUS); + i = cw_itemstore_get(conn->outgoing,CW_ITEM_AC_STATUS); if (!i) { cw_log(LOG_ERR,"Can't send AC Descriptor, no AC Status Item found"); @@ -35,7 +35,7 @@ int cw_out_ac_descriptor(struct conn *conn,struct cw_action_out * a,uint8_t *dst - i = cw_itemstore_get(conn->local,CW_ITEM_AC_HARDWARE_VERSION); + i = cw_itemstore_get(conn->outgoing,CW_ITEM_AC_HARDWARE_VERSION); if ( i ) { d += cw_put_version(d,CW_SUBELEM_AC_HARDWARE_VERSION,i->data); @@ -45,7 +45,7 @@ int cw_out_ac_descriptor(struct conn *conn,struct cw_action_out * a,uint8_t *dst } - i = cw_itemstore_get(conn->local,CW_ITEM_AC_SOFTWARE_VERSION); + i = cw_itemstore_get(conn->outgoing,CW_ITEM_AC_SOFTWARE_VERSION); if ( i ) { d += cw_put_version(d,CW_SUBELEM_AC_SOFTWARE_VERSION,i->data); diff --git a/src/capwap/cw_out_capwap_control_ip_addr_list.c b/src/capwap/cw_out_capwap_control_ip_addr_list.c index 9c562cce..fc4b4c0f 100644 --- a/src/capwap/cw_out_capwap_control_ip_addr_list.c +++ b/src/capwap/cw_out_capwap_control_ip_addr_list.c @@ -41,9 +41,9 @@ static int put_ip(void *priv, void *data) } -int cw_out_capwap_control_ip_addrs(struct conn *conn,struct cw_action_out *a,uint8_t *dst) +int cw_out_capwap_control_ip_addr_list(struct conn *conn,struct cw_action_out *a,uint8_t *dst) { - struct cw_item * item = cw_itemstore_get(conn->local,a->item_id); + struct cw_item * item = cw_itemstore_get(conn->outgoing,a->item_id); if ( !item ) { cw_log(LOG_ERR, "Can't send CAPWAP Local IPv4/IPv6 Address, not found"); diff --git a/src/capwap/cw_out_cisco_ac_descriptor.c b/src/capwap/cw_out_cisco_ac_descriptor.c index a823150a..9acc346f 100644 --- a/src/capwap/cw_out_cisco_ac_descriptor.c +++ b/src/capwap/cw_out_cisco_ac_descriptor.c @@ -11,7 +11,7 @@ int cw_out_cisco_ac_descriptor(struct conn *conn,struct cw_action_out * a,uint8_ uint8_t *d = dst+4; struct cw_item * i; - i = cw_itemstore_get(conn->local,CW_ITEM_AC_STATUS); + i = cw_itemstore_get(conn->outgoing,CW_ITEM_AC_STATUS); if (!i) { cw_log(LOG_ERR,"Can't send AC Descriptor, no AC Status Item found"); @@ -21,7 +21,7 @@ int cw_out_cisco_ac_descriptor(struct conn *conn,struct cw_action_out * a,uint8_ d+=cw_put_ac_status(d ,(struct cw_ac_status*)(i->data)); - i = cw_itemstore_get(conn->local,CW_ITEM_AC_SOFTWARE_VERSION); + i = cw_itemstore_get(conn->outgoing,CW_ITEM_AC_SOFTWARE_VERSION); if ( i ) { d += cw_put_version(d,1,i->data); diff --git a/src/capwap/cw_out_generic.c b/src/capwap/cw_out_generic.c index 3ead2172..cf9fa889 100644 --- a/src/capwap/cw_out_generic.c +++ b/src/capwap/cw_out_generic.c @@ -7,54 +7,52 @@ #include "cw_log.h" -int cw_put_item(uint8_t *dst,struct cw_item*item) +int cw_put_item(uint8_t * dst, struct cw_item *item) { - switch (item->type){ + switch (item->type) { case CW_ITEMTYPE_STR: - return cw_put_data(dst,item->data,strlen( (char*)item->data)); + return cw_put_data(dst, item->data, strlen((char *) item->data)); case CW_ITEMTYPE_BYTE: - return cw_put_byte(dst,item->byte); + return cw_put_byte(dst, item->byte); case CW_ITEMTYPE_WORD: - return cw_put_word(dst,item->word); + return cw_put_word(dst, item->word); case CW_ITEMTYPE_DWORD: - return cw_put_dword(dst,item->dword); + return cw_put_dword(dst, item->dword); } return 0; } -int cw_out_generic(struct conn *conn,struct cw_action_out *a,uint8_t *dst) // ,struct cw_item * item) +int cw_out_generic(struct conn *conn, struct cw_action_out *a, uint8_t * dst) // ,struct cw_item * item) { /* Get the item to put */ - struct cw_item *item=NULL; - if (a->get){ - item = a->get (conn,a); + struct cw_item *item = NULL; + if (a->get) { + item = a->get(conn, a); } /* Size for msg elem header depends on vendor specific payload */ - int start = a->vendor_id ? 10:4; - + int start = a->vendor_id ? 10 : 4; + int len; - if ( !item ){ - if (a->mand){ - cw_log(LOG_ERR,"Cannot send mandatory message element %d",a->elem_id); + if (!item) { + if (a->mand) { + cw_log(LOG_ERR, "Error: Cannot send mandatory message element %d - (%s)", + a->elem_id, cw_strelemp(conn->actions, a->elem_id)); } return 0; - } - else{ - len = cw_put_item(dst+start,item); + } else { + len = cw_put_item(dst + start, item); } - if (a->vendor_id) - return len + cw_put_elem_vendor_hdr(dst,a->vendor_id,a->elem_id,len); + if (a->vendor_id) + return len + cw_put_elem_vendor_hdr(dst, a->vendor_id, a->elem_id, len); - return len + cw_put_elem_hdr(dst,a->elem_id,len); + return len + cw_put_elem_hdr(dst, a->elem_id, len); } - - diff --git a/src/capwap/cw_out_wtp_board_data.c b/src/capwap/cw_out_wtp_board_data.c index 16f2402f..a86c0138 100644 --- a/src/capwap/cw_out_wtp_board_data.c +++ b/src/capwap/cw_out_wtp_board_data.c @@ -6,61 +6,65 @@ #include "capwap.h" -int cw_out_wtp_board_data(struct conn *conn,struct cw_action_out * a,uint8_t *dst) +int cw_out_wtp_board_data(struct conn *conn, struct cw_action_out *a, uint8_t * dst) { - cw_itemstore_t board_data = cw_itemstore_get_avltree(conn->local,CW_ITEM_WTP_BOARD_DATA); - if (!board_data ) { - cw_log(LOG_ERR,"Error: Can't send WTP Board Data element - not defined"); + cw_itemstore_t board_data = + cw_itemstore_get_avltree(conn->outgoing, CW_ITEM_WTP_BOARD_DATA); + if (!board_data) { + cw_log(LOG_ERR, "Error: Can't send WTP Board Data element - not defined"); return 0; } struct cw_item *i; - i=cw_itemstore_get(board_data,CW_ITEM_WTP_BOARD_VENDOR); - if (!i) { - cw_log(LOG_ERR,"Error: Can't send WTP Board Data element - no vendor defined"); + i = cw_itemstore_get(board_data, CW_ITEM_WTP_BOARD_VENDOR); + if (!i) { + cw_log(LOG_ERR, + "Error: Can't send WTP Board Data element - no vendor defined"); return 0; - } - - uint8_t *d = dst+4; - d+=cw_put_dword(d,i->dword); - - i=cw_itemstore_get(board_data,CW_ITEM_WTP_BOARD_MODELNO); - if (i) { - d+=cw_put_byte(d,CW_BOARDDATA_MODELNO ); - d+=cw_put_word(d,bstr16_len(i->data)); - d+=cw_put_data(d,bstr16_data(i->data),bstr16_len(i->data)); - } - - i=cw_itemstore_get(board_data,CW_ITEM_WTP_BOARD_SERIALNO); - if (i) { - d+=cw_put_byte(d,CW_BOARDDATA_SERIALNO ); - d+=cw_put_word(d,bstr16_len(i->data)); - d+=cw_put_data(d,bstr16_data(i->data),bstr16_len(i->data)); } - i=cw_itemstore_get(board_data,CW_ITEM_WTP_BOARD_ID); - if (i) { - d+=cw_put_byte(d,CW_BOARDDATA_BOARDID ); - d+=cw_put_word(d,bstr16_len(i->data)); - d+=cw_put_data(d,bstr16_data(i->data),bstr16_len(i->data)); + uint8_t *d = dst + 4; + d += cw_put_dword(d, i->dword); + + i = cw_itemstore_get(board_data, CW_ITEM_WTP_BOARD_MODELNO); + if (i) { + d += cw_put_word(d, CW_BOARDDATA_MODELNO); + d += cw_put_word(d, bstr16_len(i->data)); + d += cw_put_data(d, bstr16_data(i->data), bstr16_len(i->data)); + } else { + cw_log(LOG_ERR, + "Error: Can't set sub-element \"Model No.\" in WTP Board Data."); } - i=cw_itemstore_get(board_data,CW_ITEM_WTP_BOARD_REVISION); - if (i) { - d+=cw_put_byte(d,CW_BOARDDATA_REVISION ); - d+=cw_put_word(d,bstr16_len(i->data)); - d+=cw_put_data(d,bstr16_data(i->data),bstr16_len(i->data)); - } - - i=cw_itemstore_get(board_data,CW_ITEM_WTP_BOARD_MACADDRESS); - if (i) { - d+=cw_put_byte(d,CW_BOARDDATA_MACADDRESS ); - d+=cw_put_word(d,bstr_len(i->data)); - d+=cw_put_data(d,bstr_data(i->data),bstr_len(i->data)); + i = cw_itemstore_get(board_data, CW_ITEM_WTP_BOARD_SERIALNO); + if (i) { + d += cw_put_word(d, CW_BOARDDATA_SERIALNO); + d += cw_put_word(d, bstr16_len(i->data)); + d += cw_put_data(d, bstr16_data(i->data), bstr16_len(i->data)); } - int l = d-dst; - return l+cw_put_elem_hdr(dst,CW_ELEM_WTP_BOARD_DATA,l-4); + i = cw_itemstore_get(board_data, CW_ITEM_WTP_BOARD_ID); + if (i) { + d += cw_put_word(d, CW_BOARDDATA_BOARDID); + d += cw_put_word(d, bstr16_len(i->data)); + d += cw_put_data(d, bstr16_data(i->data), bstr16_len(i->data)); + } + + i = cw_itemstore_get(board_data, CW_ITEM_WTP_BOARD_REVISION); + if (i) { + d += cw_put_word(d, CW_BOARDDATA_REVISION); + d += cw_put_word(d, bstr16_len(i->data)); + d += cw_put_data(d, bstr16_data(i->data), bstr16_len(i->data)); + } + + i = cw_itemstore_get(board_data, CW_ITEM_WTP_BOARD_MACADDRESS); + if (i) { + d += cw_put_word(d, CW_BOARDDATA_MACADDRESS); + d += cw_put_word(d, bstr_len(i->data)); + d += cw_put_data(d, bstr_data(i->data), bstr_len(i->data)); + } + + int l = d - dst; + return l + cw_put_elem_hdr(dst, CW_ELEM_WTP_BOARD_DATA, l - 4); } - diff --git a/src/capwap/cw_process_msg.c b/src/capwap/cw_process_msg.c index 553d3170..5b17dcac 100644 --- a/src/capwap/cw_process_msg.c +++ b/src/capwap/cw_process_msg.c @@ -242,7 +242,7 @@ int cw_process_msg(struct conn *conn, uint8_t * rawmsg, int len) result_code = afm->end(conn, afm, rawmsg, len); } - /* if we've got a request message, we have to send a response message */ + /* 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 diff --git a/src/capwap/cw_strlist_get_str.c b/src/capwap/cw_strlist_get_str.c index 023f4156..960bfdb6 100644 --- a/src/capwap/cw_strlist_get_str.c +++ b/src/capwap/cw_strlist_get_str.c @@ -2,7 +2,7 @@ const char * cw_strlist_get_str(struct cw_str *s,int id) { - while ( s->id!=0){ + while ( s->id!=CW_STR_STOP){ if (s->id==id) break; s++; diff --git a/src/capwap/cw_util.h b/src/capwap/cw_util.h index b280bbfe..627d0ea1 100644 --- a/src/capwap/cw_util.h +++ b/src/capwap/cw_util.h @@ -46,8 +46,8 @@ extern int cw_rand(uint8_t*dst, int len); -#define cw_timer_start(t) (time(NULL)+t) -#define cw_timer_timeout(t) (time(NULL)>t ? 1 : 0) +//#define cw_timer_start(t) (time(NULL)+t) +//#define cw_timer_timeout(t) (time(NULL)>t ? 1 : 0) /** Generic macro to isolate bits from a dword */ @@ -61,6 +61,6 @@ void cw_get_missing_mand_elems(char *dst, int *l); -extern const char * cw_msgtostr(int type); +//extern const char * cw_msgtostr(int type); #endif diff --git a/src/capwap/dbg.c b/src/capwap/dbg.c index 2efef61f..5a06e8de 100644 --- a/src/capwap/dbg.c +++ b/src/capwap/dbg.c @@ -1,9 +1,30 @@ +/* + This file is part of libcapwap. + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ #include "capwap.h" #include "dbg.h" +#include "sock.h" + #include "cw_log.h" +/** + * Put a list of missing mandatory message elements to debug output + */ void cw_dbg_missing_mand(int level,struct conn *conn,cw_action_in_t ** ml,int n,cw_action_in_t *a) { if (!cw_dbg_is_level(DBG_ELEM) || n==0) @@ -16,8 +37,34 @@ void cw_dbg_missing_mand(int level,struct conn *conn,cw_action_in_t ** ml,int n, for(i=0; iactions,ml[i]->elem_id)); - } - cw_dbg(DBG_ELEM,"Missing mandatory elements: [%s]",buffer); } + + + +void cw_dbg_packet(struct conn *conn, uint8_t * packet, int len) +{ + if (!cw_dbg_is_level(DBG_CW_PKT_IN || DBG_CW_PKT_OUT)) + return; + + + /* print the header */ + char hdr[200]; + hdr_print(hdr, packet, len); + + + 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; + + } + + cw_dbg_dmp(DBG_CW_PKT_DMP, packet, len, + "Processing packet from %s, len=%d\n%s\n\tDump:", + sock_addr2str(&conn->addr), len, hdr); + +} + + diff --git a/src/capwap/dbg.h b/src/capwap/dbg.h index e1ad3ea7..99d81754 100644 --- a/src/capwap/dbg.h +++ b/src/capwap/dbg.h @@ -5,11 +5,13 @@ void cw_dbg_elem_(struct conn * conn, int msg, int msgelem, const uint8_t * msgbuf, int len); void cw_dbg_missing_mand(int level,struct conn *conn,cw_action_in_t ** ml,int n,cw_action_in_t *a); +void cw_dbg_packet(struct conn *conn, uint8_t * packet, int len); #ifdef WITH_CW_LOG_DEBUG - #define cw_dbg_elem(conn,msgtype,msgelemtype,msgbuf,msglen) cw_dbg_elem_(conn,msgtype,msgelemtype,msgbuf,msglen) + #define cw_dbg_elem(conn,msgtype,msgelemtype,msgbuf,msglen)\ + cw_dbg_elem_(conn,msgtype,msgelemtype,msgbuf,msglen) #else @@ -17,3 +19,20 @@ void cw_dbg_missing_mand(int level,struct conn *conn,cw_action_in_t ** ml,int n, #endif #endif + + + + +/** + * @defgroup DebugOptions Dbug Options + * @{ + */ +#define CW_DBG_PKT_IN 0x00000001 /* Headers of incoming CAPWAP packets */ +#define CW_DBG_PKT_OUT 0x00000002 /* Headers of outgoing CAPWAP packets */ + + + +/**@}*/ + + + diff --git a/src/capwap/dtls_gnutls.c b/src/capwap/dtls_gnutls.c index 328ee2a6..7ef7042c 100644 --- a/src/capwap/dtls_gnutls.c +++ b/src/capwap/dtls_gnutls.c @@ -17,6 +17,7 @@ */ #include +#include #include @@ -68,8 +69,15 @@ int dtls_gnutls_read(struct conn * conn, uint8_t *buffer, int len) struct dtls_gnutls_data * d = conn->dtls_data; int rc = gnutls_record_recv_seq(d->session,buffer,len,seq); - if ( rc == GNUTLS_E_AGAIN ) - return 0; + if (rc==0) { + errno = ECONNRESET; + return -1; + } + + if ( rc == GNUTLS_E_AGAIN ){ + errno = EAGAIN; + return -1; + } if ( rc < 0 ){ cw_log(LOG_ERR, "DTLS - read error: %s", gnutls_strerror(rc)); diff --git a/src/capwap/dtls_gnutls.h b/src/capwap/dtls_gnutls.h index 5052aeaa..c423dc89 100644 --- a/src/capwap/dtls_gnutls.h +++ b/src/capwap/dtls_gnutls.h @@ -33,6 +33,7 @@ extern int dtls_gnutls_accept(struct conn * conn); extern int dtls_gnutls_connect(struct conn * conn); extern const char * dtls_gnutls_get_cipher(struct conn * conn); struct dtls_ssl_cert dtls_gnutls_get_peers_cert(struct conn * conn,unsigned int n); +extern int dtls_gnutls_shutdown(struct conn *conn); /* functions used only by capwap libray */ diff --git a/src/capwap/dtls_gnutls_accept.c b/src/capwap/dtls_gnutls_accept.c index 52831e78..6a946f82 100644 --- a/src/capwap/dtls_gnutls_accept.c +++ b/src/capwap/dtls_gnutls_accept.c @@ -27,7 +27,7 @@ #include "conn.h" #include "cw_log.h" #include "sock.h" -#include "cw_util.h" +#include "capwap.h" #include "dtls_gnutls.h" diff --git a/src/capwap/dtls_gnutls_bio.c b/src/capwap/dtls_gnutls_bio.c index a5b2d6d3..b01e9a78 100644 --- a/src/capwap/dtls_gnutls_bio.c +++ b/src/capwap/dtls_gnutls_bio.c @@ -23,7 +23,7 @@ #include "dtls.h" #include "dtls_gnutls.h" -#include "cw_util.h" +#include "capwap.h" diff --git a/src/capwap/format.h b/src/capwap/format.h index a1d49cf3..6881fcfd 100644 --- a/src/capwap/format.h +++ b/src/capwap/format.h @@ -54,4 +54,5 @@ extern int cw_format_hex_bytes(char *dst, const char *format, const char *delim, #define cw_format_hex cw_format_hexl + #endif diff --git a/src/capwap/intavltree.h b/src/capwap/intavltree.h index 3b53bae5..a4fb468e 100644 --- a/src/capwap/intavltree.h +++ b/src/capwap/intavltree.h @@ -4,6 +4,7 @@ #include "avltree.h" extern struct avltree * intavltree_create(); +typedef struct avltree * intavltree_t; int * intavltree_add(struct avltree * t, int val); #define intavltree_destroy(t) avltree_destroy(t) diff --git a/src/capwap/itemstore.c b/src/capwap/itemstore.c index adc65c8a..d22b997b 100644 --- a/src/capwap/itemstore.c +++ b/src/capwap/itemstore.c @@ -10,6 +10,7 @@ static inline void cw_itemstore_del_data(void *e) { struct cw_item *item = (struct cw_item *) e; + switch (item->type) { case CW_ITEMTYPE_DATA: case CW_ITEMTYPE_STR: @@ -91,6 +92,7 @@ int cw_itemstore_set_dword(cw_itemstore_t s, uint32_t id, uint32_t dword) struct cw_item *i = cw_item_create(s, id); if (!i) return 0; + i->dword = dword; i->type = CW_ITEMTYPE_DWORD; return 1; @@ -272,7 +274,12 @@ int cw_itemstore_set(cw_itemstore_t itemstore, uint32_t item_id, int item_type, case CW_ITEMTYPE_BYTE: cw_itemstore_set_byte(itemstore,item_id,*data); break; - + case CW_ITEMTYPE_WORD: + cw_itemstore_set_word(itemstore,item_id,*data); + break; + case CW_ITEMTYPE_DWORD: + cw_itemstore_set_dword(itemstore,item_id,*data); + break; case CW_ITEMTYPE_STR: cw_itemstore_set_strn(itemstore,item_id,(char*)data,len); break; diff --git a/src/capwap/itemstore.h b/src/capwap/itemstore.h index 545efd36..72035f59 100644 --- a/src/capwap/itemstore.h +++ b/src/capwap/itemstore.h @@ -57,6 +57,7 @@ struct cw_item { uint32_t dword; }; }; +typedef struct cw_item cw_item_t; typedef struct avltree *cw_itemstore_t; @@ -78,8 +79,7 @@ extern int cw_itemstore_set_dword(cw_itemstore_t s, uint32_t id, uint32_t dword) extern int cw_itemstore_set_word(cw_itemstore_t s, uint32_t id, uint32_t word); extern int cw_itemstore_set_byte(cw_itemstore_t s, uint32_t id, uint8_t byte); extern int cw_itemstore_set_vendorstr(cw_itemstore_t s, uint32_t id, - uint32_t vendor_id, uint8_t * vendorstr, - int len); + uint32_t vendor_id, uint8_t * vendorstr, int len); int cw_itemstore_set_avltree(cw_itemstore_t s, uint32_t id, struct avltree *t); int cw_itemstore_set_bstr16n(cw_itemstore_t s, uint32_t id, uint8_t * data, int len); @@ -87,24 +87,43 @@ int cw_itemstore_set_bstr16n(cw_itemstore_t s, uint32_t id, uint8_t * data, int extern int cw_itemstore_set_data(cw_itemstore_t s, uint32_t id, const uint8_t * data, int len); -static inline char * cw_itemstore_get_str(cw_itemstore_t s,uint32_t id) { - struct cw_item *i = cw_itemstore_get(s,id); +static inline char *cw_itemstore_get_str(cw_itemstore_t s, uint32_t id) +{ + struct cw_item *i = cw_itemstore_get(s, id); if (!i) return NULL; return i->data; }; -static inline struct avltree * cw_itemstore_get_avltree(cw_itemstore_t s,uint32_t id){ - struct cw_item *i = cw_itemstore_get(s,id); +static inline struct avltree *cw_itemstore_get_avltree(cw_itemstore_t s, uint32_t id) +{ + struct cw_item *i = cw_itemstore_get(s, id); if (!i) return NULL; - if (i->type!=CW_ITEMTYPE_AVLTREE) + if (i->type != CW_ITEMTYPE_AVLTREE) return NULL; return i->data; } +static inline struct avltree *cw_itemstore_get_avltree_c(cw_itemstore_t s, uint32_t id, + struct avltree *(creator) ()) +{ + struct avltree *avltree = cw_itemstore_get_avltree(s, id); + if (avltree){ + return avltree; + } + + avltree = creator(); + if (!avltree) + return NULL; + cw_itemstore_set_avltree(s, id, avltree); + return avltree; +} + + + extern void *cw_item_get_data_ptr(struct cw_item *item); extern void cw_item_release_data_ptr(struct cw_item *item, void *data); @@ -113,6 +132,7 @@ int cw_itemstore_set_fun(cw_itemstore_t s, uint32_t id, void *(*funget) (void *arg), void (*funfree) (void *arg, void *data), void *arg); -int cw_itemstore_set(cw_itemstore_t itemstore, uint32_t item_id, int item_type, uint8_t *data, int len); +int cw_itemstore_set(cw_itemstore_t itemstore, uint32_t item_id, int item_type, + uint8_t * data, int len); #endif diff --git a/src/capwap/strheap.h b/src/capwap/strheap.h index 6de3d07d..f606e16c 100644 --- a/src/capwap/strheap.h +++ b/src/capwap/strheap.h @@ -9,10 +9,12 @@ typedef struct avltree * cw_strheap_t; struct cw_str { - uint32_t id; + int id; const char *str; }; +#define CW_STR_STOP -1138 + extern cw_strheap_t cw_strheap_create(); extern int cw_strheap_register_strings(cw_strheap_t h, struct cw_str *s); diff --git a/src/wtp/Makefile b/src/wtp/Makefile index dd9763d2..372de683 100644 --- a/src/wtp/Makefile +++ b/src/wtp/Makefile @@ -21,7 +21,7 @@ endif CFLAGS += -Os -Wall -g -CFLAGS += -Os -Wall +#CFLAGS += -Os -Wall LDFLAGS += -L../../src/capwap/$(ARCH) diff --git a/src/wtp/discovery.c b/src/wtp/discovery.c index 378b08d8..9336735b 100644 --- a/src/wtp/discovery.c +++ b/src/wtp/discovery.c @@ -31,6 +31,8 @@ #include "capwap/acinfo.h" #include "capwap/sock.h" #include "capwap/cw_util.h" +#include "capwap/aciplist.h" +#include "capwap/acpriolist.h" #include "wtp.h" @@ -41,26 +43,109 @@ +cw_aciplist_t cw_select_ac(struct conn *conn, cw_itemstore_t dis) +{ + + cw_aciplist_t aciplist = cw_aciplist_create(); + if (!aciplist) { + cw_log(LOG_ERROR, "Can't allocate aciplist"); + return NULL; + } + + + /* get the AC Name with Priority list */ + cw_acpriolist_t priolist; + priolist = cw_itemstore_get_avltree(conn->local, CW_ITEM_AC_PRIO_LIST); + + cw_aciplist_t resultlist=cw_aciplist_create(); + + + DEFINE_AVLITER(i, dis); + avliter_foreach(&i){ + cw_itemstore_t ac = ((cw_item_t *) (avliter_get(&i)))->data; + + char *ac_name = cw_itemstore_get_str(ac, CW_ITEM_AC_NAME); + + int prio = 256; + if (ac_name) { + /* See if we can find AC Name in Priority List */ + if (priolist) + prio = cw_acpriolist_get(priolist, ac_name); + else + prio = 256; + + } + + cw_aciplist_t acips = + cw_itemstore_get_avltree(ac, CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST); + + DEFINE_AVLITER(i2, acips); + avliter_foreach(&i2){ + cw_acip_t *acip = avliter_get(&i2); + cw_acip_t *n = malloc(sizeof(cw_acip_t)); + memcpy(n,acip,sizeof(cw_acip_t)); + + n->wtp_count |= prio<<16; + cw_aciplist_del(resultlist,n); + cw_aciplist_add(resultlist,n); + } + + } + + return resultlist; + +} + + + static int run_discovery(struct conn *conn) { - conn->capwap_state=CW_STATE_DISCOVERY; - cw_itemstore_set_byte(conn->local,CW_ITEM_DISCOVERY_TYPE,CW_DISCOVERY_TYPE_UNKNOWN); +// conn->incomming = cw_itemstore_create(); + + conn->capwap_state = CW_STATE_DISCOVERY; + cw_itemstore_set_byte(conn->outgoing, CW_ITEM_DISCOVERY_TYPE, + CW_DISCOVERY_TYPE_UNKNOWN); - cw_init_request(conn,CW_MSG_DISCOVERY_REQUEST); - cw_put_msg(conn,conn->req_buffer); - conn_send_msg(conn,conn->req_buffer); + cw_init_request(conn, CW_MSG_DISCOVERY_REQUEST); + cw_put_msg(conn, conn->req_buffer); + conn_send_msg(conn, conn->req_buffer); - time_t timer = cw_timer_start(10); + time_t timer = cw_timer_start(0); - while (!cw_timer_timeout(timer) - && conn->capwap_state == CW_STATE_DISCOVERY) { - cw_read_messages(conn); - printf ("Got one annswer\n"); - - } + cw_itemstore_t discs; + while (!cw_timer_timeout(timer) + && conn->capwap_state == CW_STATE_DISCOVERY) { + avltree_del_all(conn->incomming); + + int rc = cw_read_messages(conn); + + if (rc<0) { + if (errno==EAGAIN) + continue; + + cw_log(LOG_ERROR,"Error reading messages: %s",strerror(errno)); + break; + } + discs = cw_itemstore_get_avltree(conn->remote, CW_ITEM_DISCOVERIES); + } + + + int i; + + cw_aciplist_t list = cw_select_ac(conn, discs); + + DEFINE_AVLITER(ii,list); + avliter_foreach(&ii){ + cw_acip_t * ip = avliter_get(&ii); + + } + + avltree_del_all(conn->remote); + + cw_itemstore_set_avltree(conn->local,CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST,list); return 0; } @@ -70,50 +155,50 @@ static int run_discovery(struct conn *conn) /** * Run discovery for on address (eg broadcast 255.255.255.255) - */ + */ static int cw_run_discovery(struct conn *conn, const char *acaddr) { - /* get addr of destination */ + /* get addr of destination */ struct addrinfo hints; - struct addrinfo * res,*res0; - memset(&hints,0,sizeof(hints)); + struct addrinfo *res, *res0; + memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; hints.ai_family = PF_UNSPEC; - int rc = getaddrinfo(acaddr,conf_control_port,&hints,&res0); - if(rc){ - cw_log(LOG_ERR,"Can't connect to AC %s: %s",acaddr,gai_strerror(rc)); + int rc = getaddrinfo(acaddr, conf_control_port, &hints, &res0); + if (rc) { + cw_log(LOG_ERR, "Can't connect to AC %s: %s", acaddr, gai_strerror(rc)); return 0; } - for(res=res0; res; res=res->ai_next) - { + for (res = res0; res; res = res->ai_next) { int sockfd; int opt; - sockfd=socket(res->ai_family,SOCK_DGRAM,0); - if (sockfd == -1){ - cw_log(LOG_ERR,"Can't create socket for %s: %s",acaddr,strerror(errno)); + sockfd = socket(res->ai_family, SOCK_DGRAM, 0); + if (sockfd == -1) { + cw_log(LOG_ERR, "Can't create socket for %s: %s", acaddr, + strerror(errno)); continue; } - - opt = 1; - if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt))<0){ - cw_log(LOG_ERR,"Can't set broadcast sockopt"); - } - sock_set_recvtimeout(sockfd,1); - sock_set_dontfrag(sockfd,0); - sock_copyaddr(&conn->addr,res->ai_addr); - conn->sock=sockfd; + opt = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) < 0) { + cw_log(LOG_ERR, "Can't set broadcast sockopt"); + } + sock_set_recvtimeout(sockfd, 1); + sock_set_dontfrag(sockfd, 0); + + sock_copyaddr(&conn->addr, res->ai_addr); + conn->sock = sockfd; run_discovery(conn); close(sockfd); - + } freeaddrinfo(res0); @@ -124,7 +209,8 @@ static int cw_run_discovery(struct conn *conn, const char *acaddr) int discovery() { - struct conn * conn = get_conn(); - cw_run_discovery(conn,"255.255.255.255"); + struct conn *conn = get_conn(); + cw_run_discovery(conn, "255.255.255.255"); + conn->capwap_state=CW_STATE_JOIN; return 0; } diff --git a/src/wtp/join.c b/src/wtp/join.c index 7c392348..f3042cd4 100644 --- a/src/wtp/join.c +++ b/src/wtp/join.c @@ -12,6 +12,8 @@ #include "capwap/cw_log.h" #include "capwap/sock.h" #include "capwap/dtls.h" +#include "capwap/aciplist.h" +#include "capwap/capwap_items.h" /* #define acinfo_log acinfo_log_ @@ -88,8 +90,129 @@ acinfo.result_code=99; } +*/ + +int run_join_d(struct sockaddr *sa) +{ + struct conn *conn = get_conn(); + conn->capwap_state=CW_STATE_JOIN; + + int sockfd; + int rc; + + sockfd = socket(AF_INET,SOCK_DGRAM,0); + if (sockfd==-1){ + cw_log(LOG_ERR,"Can't create socket: %s\n",strerror(errno)); + return -1; + } + sock_set_recvtimeout(sockfd,1); + + rc = connect(sockfd,(struct sockaddr*)sa,sock_addrlen((struct sockaddr*)sa)); + + if (rc<0){ + cw_log(LOG_ERR,"Can't connect to %s: %s\n",sock_addr2str(sa),strerror(errno)); + close(sockfd); + return -1; + } + + conn->sock=sockfd; + sock_copyaddr(&conn->addr,sa); + + cw_dbg (DBG_DTLS,"Establishing DTLS session with %s",sock_addr2str(sa)); + + if (conf_dtls_psk){ + conn->dtls_psk=conf_dtls_psk; + conn->dtls_psk_len=strlen(conn->dtls_psk); + conn->dtls_cipher=conf_dtls_cipher; + } + + if (conf_sslkeyfilename && conf_sslcertfilename){ + + conn->dtls_key_file = conf_sslkeyfilename; + conn->dtls_cert_file = conf_sslcertfilename; + conn->dtls_key_pass = conf_sslkeypass; + conn->dtls_cipher=conf_dtls_cipher; + + } + + rc = dtls_connect(conn); + if (rc!=1){ + dtls_shutdown(conn); + cw_log(LOG_ERR,"Can't establish DTLS connection to %s", sock_addr2str(sa)); + close(sockfd); + return 0; + } + + + cw_dbg (DBG_DTLS,"DTLS Connection successful established with %s",sock_addr2str(sa)); + + + + return 1; +} + + +int run_join(struct conn * conn) +{ + +// cw_init_request(conn, CW_MSG_JOIN_REQUEST); +// if ( cw_put_msg(conn, conn->req_buffer) == -1 ) +// return 0; +// +// conn_send_msg(conn, conn->req_buffer); + + int rc = cw_send_request(conn,CW_MSG_JOIN_REQUEST); + + if (rc >=0 ) { + cw_dbg(DBG_ELEM,"Join Result: %d - %s",rc,cw_strresult(rc)); + + } + if (rc != 0 && rc != 2) { + cw_log(LOG_ERR,"Join to %s was not successful.",sock_addr2str(&conn->addr)); + return 0; + } + + + return 1; +} + + + +int join() +{ + struct conn * conn = get_conn(); + cw_aciplist_t iplist = cw_itemstore_get_avltree(conn->local,CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST); + if (!iplist){ + cw_log(LOG_ERR,"No Ips to join controller."); + return 0; + } + + DEFINE_AVLITER(ii,iplist); + avliter_foreach(&ii){ + cw_acip_t * ip = avliter_get(&ii); + + cw_dbg(DBG_ELEM,"Going to join CAWAP controller on %s",sock_addr2str(&ip->ip)); + + int rc = run_join_d((struct sockaddr*)&ip->ip); + if (!rc) + continue; + rc = run_join(conn); + if (rc){ + conn->capwap_state=CW_STATE_CONFIGURE; + return 1; + } + + + + } + + return 0; + +} + +/* int join(struct sockaddr *sa) { int sockfd; diff --git a/src/wtp/wtp_main.c b/src/wtp/wtp_main.c index 2da775de..3f72409b 100644 --- a/src/wtp/wtp_main.c +++ b/src/wtp/wtp_main.c @@ -8,6 +8,7 @@ #include "capwap/conn.h" #include "capwap/cw_log.h" #include "capwap/dtls.h" +#include "capwap/acpriolist.h" #include "wtp.h" #include "wtp_conf.h" @@ -43,8 +44,11 @@ int main() cw_register_actions_capwap_wtp(&capwap_actions); + ////cw_register_actions_capwap_80211_wtp(&capwap_actions); + conn->actions = &capwap_actions; - conn->remote = cw_itemstore_create(); + conn->outgoing = cw_itemstore_create(); + conn->incomming = cw_itemstore_create(); conn->local = cw_itemstore_create(); cw_itemstore_t board_data = cw_itemstore_create(); @@ -59,9 +63,20 @@ int main() - cw_itemstore_set_avltree(conn->local, CW_ITEM_WTP_BOARD_DATA, board_data); + cw_itemstore_set_avltree(conn->outgoing, CW_ITEM_WTP_BOARD_DATA, board_data); + + cw_acpriolist_t acprios = cw_acpriolist_create(); + cw_acpriolist_set(acprios,"Master AC",strlen("Master AC"),1); + cw_acpriolist_set(acprios,"AC8new",strlen("AC8new"),12); + + cw_itemstore_set_avltree(conn->local,CW_ITEM_AC_PRIO_LIST,acprios); + + cw_itemstore_set_str(conn->local,CW_ITEM_LOCATION_DATA,"Berlin"); + cw_itemstore_set_str(conn->local,CW_ITEM_WTP_NAME,"WTP Tube"); + discovery(); + join(); }