More work on CW VM code ..
FossilOrigin-Name: 3b0cb324535527b32d0e938b03151c75f6100ca2059fc121e2c4d350a8caf8a4
This commit is contained in:
parent
e148b7c9f6
commit
c43f85b2a6
@ -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) \
|
||||
|
@ -33,6 +33,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)
|
||||
return -1;
|
||||
|
@ -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,6 +169,22 @@ 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_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);
|
||||
}
|
||||
|
||||
struct cw_item *cw_out_get_remote(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,19 +32,42 @@ 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: 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}
|
||||
,
|
||||
|
||||
/* Element CAPWAP Control IPv4 Address */
|
||||
|
||||
|
||||
|
||||
@ -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,8 +19,11 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "capwap.h"
|
||||
#include "dbg.h"
|
||||
|
||||
#include "cw_log.h"
|
||||
#include "cw_util.h"
|
||||
|
||||
@ -29,52 +32,251 @@
|
||||
|
||||
#include <stdio.h> //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);
|
||||
return 0;
|
||||
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);
|
||||
}
|
||||
|
||||
uint32_t val;
|
||||
void cw_init_request(struct conn *conn, int msg_id)
|
||||
{
|
||||
uint8_t *buffer = conn->req_buffer;
|
||||
|
||||
/* first dword of header is the message type*/
|
||||
cwrmsg->type = ntohl(*((uint32_t*)(msg)));
|
||||
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);
|
||||
|
||||
/* second dword = seqnum, len and flags */
|
||||
val = ntohl(*((uint32_t*)(msg+4)));
|
||||
|
||||
cwrmsg->seqnum = cw_get_dword_bits(val,0,8);
|
||||
}
|
||||
|
||||
cwrmsg->msgelems_len=cw_get_dword_bits(val,8,16)-3;
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
// ch->flags=CW_GET_DWORD_BITS(val,24,8);
|
||||
cwrmsg->msgelems=msg+8;
|
||||
|
||||
if (8+cwrmsg->msgelems_len != len){
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
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 (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);
|
||||
|
||||
@ -83,8 +285,8 @@ static int process_message(struct conn * conn,uint8_t *rawmsg,int rawlen,int (*c
|
||||
|
||||
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
|
||||
@ -99,74 +301,55 @@ static int process_message(struct conn * conn,uint8_t *rawmsg,int rawlen,int (*c
|
||||
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;
|
||||
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;
|
||||
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",
|
||||
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;
|
||||
// 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) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -174,7 +357,9 @@ int conn_process_packet(struct conn * conn, uint8_t *packet, int len,int (*cb)(v
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -192,7 +377,9 @@ int conn_process_packet(struct conn * conn, uint8_t *packet, int len,int (*cb)(v
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
@ -210,7 +397,9 @@ int conn_process_packet(struct conn * conn, uint8_t *packet, int len,int (*cb)(v
|
||||
|
||||
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);
|
||||
@ -241,12 +430,11 @@ 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;
|
||||
return rc;
|
||||
}
|
||||
|
||||
//extern int cw_process_msg(struct conn * conn,uint8_t*msg,int len);
|
||||
//cw_process_msg(conn,packet,len);
|
||||
|
||||
@ -257,8 +445,7 @@ int conn_process_packet(struct conn * conn, uint8_t *packet, int len,int (*cb)(v
|
||||
//}
|
||||
|
||||
//msg_4*((val >> 19) & 0x1f);
|
||||
process_message(conn,packet,len,cb,cbarg);
|
||||
return 1;
|
||||
return process_message(conn, packet, len, NULL,NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -274,10 +461,12 @@ int cw_read_messages(struct conn *conn)
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -13,14 +13,25 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,39 @@ int cw_in_generic(struct conn *conn,struct cw_action_in * a,uint8_t *data,int le
|
||||
}
|
||||
|
||||
|
||||
cw_itemstore_set(conn->remote,a->item_id,a->itemtype,data,len);
|
||||
cw_itemstore_t itemstore = conn->incomming;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -28,6 +28,10 @@
|
||||
#include <stdint.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#ifndef LOG_ERROR
|
||||
#define LOG_ERROR LOG_ERR
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup DebugOptions Dbug Options
|
||||
* @{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -42,11 +42,11 @@ int cw_out_generic(struct conn *conn,struct cw_action_out *a,uint8_t *dst) // ,s
|
||||
int len;
|
||||
if (!item) {
|
||||
if (a->mand) {
|
||||
cw_log(LOG_ERR,"Cannot send mandatory message element %d",a->elem_id);
|
||||
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{
|
||||
} else {
|
||||
len = cw_put_item(dst + start, item);
|
||||
}
|
||||
|
||||
@ -56,5 +56,3 @@ int cw_out_generic(struct conn *conn,struct cw_action_out *a,uint8_t *dst) // ,s
|
||||
|
||||
return len + cw_put_elem_hdr(dst, a->elem_id, len);
|
||||
}
|
||||
|
||||
|
||||
|
@ -8,7 +8,8 @@
|
||||
|
||||
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);
|
||||
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;
|
||||
@ -17,7 +18,8 @@ int cw_out_wtp_board_data(struct conn *conn,struct cw_action_out * a,uint8_t *ds
|
||||
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");
|
||||
cw_log(LOG_ERR,
|
||||
"Error: Can't send WTP Board Data element - no vendor defined");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -26,35 +28,38 @@ int cw_out_wtp_board_data(struct conn *conn,struct cw_action_out * a,uint8_t *ds
|
||||
|
||||
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, 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_SERIALNO);
|
||||
if (i) {
|
||||
d+=cw_put_byte(d,CW_BOARDDATA_SERIALNO );
|
||||
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));
|
||||
}
|
||||
|
||||
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, 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_byte(d,CW_BOARDDATA_REVISION );
|
||||
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_byte(d,CW_BOARDDATA_MACADDRESS );
|
||||
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));
|
||||
}
|
||||
@ -63,4 +68,3 @@ int cw_out_wtp_board_data(struct conn *conn,struct cw_action_out * a,uint8_t *ds
|
||||
return l + cw_put_elem_hdr(dst, CW_ELEM_WTP_BOARD_DATA, l - 4);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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++;
|
||||
|
@ -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
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#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; i<n; i++) {
|
||||
p+=sprintf(p,"%s",delim); delim=", ";
|
||||
p+=sprintf(p,"%s",cw_strelemp(conn->actions,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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
|
||||
@ -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));
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#include "dtls.h"
|
||||
#include "dtls_gnutls.h"
|
||||
#include "cw_util.h"
|
||||
#include "capwap.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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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,7 +87,8 @@ 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) {
|
||||
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;
|
||||
@ -95,7 +96,8 @@ static inline char * cw_itemstore_get_str(cw_itemstore_t s,uint32_t id) {
|
||||
|
||||
};
|
||||
|
||||
static inline struct avltree * cw_itemstore_get_avltree(cw_itemstore_t s,uint32_t 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;
|
||||
@ -105,6 +107,23 @@ static inline struct avltree * cw_itemstore_get_avltree(cw_itemstore_t s,uint32_
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -21,7 +21,7 @@ endif
|
||||
|
||||
|
||||
CFLAGS += -Os -Wall -g
|
||||
CFLAGS += -Os -Wall
|
||||
#CFLAGS += -Os -Wall
|
||||
LDFLAGS += -L../../src/capwap/$(ARCH)
|
||||
|
||||
|
||||
|
@ -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,10 +43,68 @@
|
||||
|
||||
|
||||
|
||||
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->incomming = cw_itemstore_create();
|
||||
|
||||
conn->capwap_state = CW_STATE_DISCOVERY;
|
||||
cw_itemstore_set_byte(conn->local,CW_ITEM_DISCOVERY_TYPE,CW_DISCOVERY_TYPE_UNKNOWN);
|
||||
cw_itemstore_set_byte(conn->outgoing, CW_ITEM_DISCOVERY_TYPE,
|
||||
CW_DISCOVERY_TYPE_UNKNOWN);
|
||||
|
||||
|
||||
cw_init_request(conn, CW_MSG_DISCOVERY_REQUEST);
|
||||
@ -52,15 +112,40 @@ static int run_discovery(struct conn *conn)
|
||||
conn_send_msg(conn, conn->req_buffer);
|
||||
|
||||
|
||||
time_t timer = cw_timer_start(10);
|
||||
time_t timer = cw_timer_start(0);
|
||||
|
||||
cw_itemstore_t discs;
|
||||
|
||||
while (!cw_timer_timeout(timer)
|
||||
&& conn->capwap_state == CW_STATE_DISCOVERY) {
|
||||
cw_read_messages(conn);
|
||||
printf ("Got one annswer\n");
|
||||
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;
|
||||
}
|
||||
@ -88,14 +173,14 @@ static int cw_run_discovery(struct conn *conn, const char *acaddr)
|
||||
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));
|
||||
cw_log(LOG_ERR, "Can't create socket for %s: %s", acaddr,
|
||||
strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -126,5 +211,6 @@ int discovery()
|
||||
{
|
||||
struct conn *conn = get_conn();
|
||||
cw_run_discovery(conn, "255.255.255.255");
|
||||
conn->capwap_state=CW_STATE_JOIN;
|
||||
return 0;
|
||||
}
|
||||
|
123
src/wtp/join.c
123
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;
|
||||
|
@ -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();
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user