More work on CW VM code ..

FossilOrigin-Name: 3b0cb324535527b32d0e938b03151c75f6100ca2059fc121e2c4d350a8caf8a4
This commit is contained in:
7u83@mail.ru 2015-04-10 15:14:55 +00:00
parent e148b7c9f6
commit c43f85b2a6
59 changed files with 1188 additions and 459 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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");

View File

@ -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)
{

View File

@ -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.

View File

@ -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) \

View File

@ -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)

View File

@ -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

View File

@ -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,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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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}
,

View File

@ -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}

View File

@ -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 */
};

View File

@ -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"}
};

View File

@ -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"}
}

View File

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

View File

@ -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" }
};

View File

@ -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" }
};

View File

@ -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);

View File

@ -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();
}

View File

@ -19,72 +19,274 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "capwap.h"
#include "dbg.h"
#include "cw_log.h"
#include "cw_util.h"
#include "conn.h"
#include "sock.h"
#include <stdio.h> //tube
#include <stdio.h> //tube
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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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));

View File

@ -28,6 +28,10 @@
#include <stdint.h>
#include <syslog.h>
#ifndef LOG_ERROR
#define LOG_ERROR LOG_ERR
#endif
/**
* @defgroup DebugOptions Dbug Options
* @{

View File

@ -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);
}
}
*/

View File

@ -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);

View File

@ -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");

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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++;

View File

@ -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

View File

@ -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);
}

View File

@ -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 */
/**@}*/

View File

@ -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));

View File

@ -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 */

View File

@ -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"

View File

@ -23,7 +23,7 @@
#include "dtls.h"
#include "dtls_gnutls.h"
#include "cw_util.h"
#include "capwap.h"

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -21,7 +21,7 @@ endif
CFLAGS += -Os -Wall -g
CFLAGS += -Os -Wall
#CFLAGS += -Os -Wall
LDFLAGS += -L../../src/capwap/$(ARCH)

View File

@ -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;
}

View File

@ -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;

View File

@ -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();
}