Lots done in move to typeless
This commit is contained in:
parent
b158544f1a
commit
459e2e2aeb
@ -178,20 +178,6 @@ int main (int argc, char *argv[])
|
||||
|
||||
|
||||
|
||||
/*
|
||||
cw_Cfg_t * tcfg = cw_cfg_create();
|
||||
cw_cfg_set(tcfg,"tube.0","hallo");
|
||||
cw_cfg_set(tcfg,"tube.1","welt");
|
||||
cw_cfg_set(tcfg,"tube.2","der guten laune");
|
||||
cw_cfg_dump(tcfg);
|
||||
|
||||
printf("Next Index: %d\n",cw_cfg_get_next_index(tcfg,"kinder"));
|
||||
|
||||
|
||||
exit(0);
|
||||
*/
|
||||
|
||||
|
||||
/* parse arguments */
|
||||
parse_args (argc, argv, &bootcfg);
|
||||
|
||||
@ -213,6 +199,39 @@ int main (int argc, char *argv[])
|
||||
|
||||
|
||||
cw_log_name = "AC-Tube";
|
||||
|
||||
/*
|
||||
|
||||
{
|
||||
int rc;
|
||||
cw_Cfg_t * cfg = global_cfg;
|
||||
struct cw_Cfg_entry e, *result;
|
||||
|
||||
e.key="hi";
|
||||
|
||||
rc = cw_cfg_base_exists(cfg,"ac-descriptor");
|
||||
if (!rc ){
|
||||
printf("No!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("RESULT: %d\n",rc);
|
||||
|
||||
cw_cfg_set(tcfg,"tube.0","hallo");
|
||||
cw_cfg_set(tcfg,"tube.1","welt");
|
||||
cw_cfg_set(tcfg,"tube.2","der guten laune");
|
||||
cw_cfg_dump(tcfg);
|
||||
|
||||
printf("Next Index: %d\n",cw_cfg_get_next_index(tcfg,"kinder"));
|
||||
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
start_shell();
|
||||
|
@ -54,3 +54,15 @@ ac-descriptor/stations: 0
|
||||
|
||||
capwap-control-ip-address/address.0: 192.168.0.14
|
||||
|
||||
|
||||
|
||||
#
|
||||
# CAPWAP Timers
|
||||
#
|
||||
capwap-timers/change-state-pending-timer: Word: 3
|
||||
capwap-timers/data-check-timer: Word: 10
|
||||
capwap-timers/echo-interval :Byte: 30
|
||||
capwap-timers/max-discovery-interval :Byte: 10
|
||||
|
||||
|
||||
|
||||
|
@ -131,10 +131,13 @@ void set_cmd(struct shelldata *sd, const char *str)
|
||||
{
|
||||
struct cw_Conn * conn;
|
||||
struct cw_Val_Reader r;
|
||||
char key[CW_KTV_MAX_KEY_LEN];
|
||||
char type[CW_KTV_MAX_KEY_LEN];
|
||||
char key[CW_CFG_MAX_KEY_LEN];
|
||||
char type[CW_CFG_MAX_KEY_LEN];
|
||||
char val[2048];
|
||||
cw_ktv_init_str_reader(&r,str,strlen(str));
|
||||
|
||||
stop();
|
||||
|
||||
// cw_ktv_init_str_reader(&r,str,strlen(str));
|
||||
|
||||
cw_ktv_parse_string(&r,key,type,val);
|
||||
/*cw_ktv_parse_string(key,type,val, 2048);*/
|
||||
@ -145,7 +148,7 @@ void set_cmd(struct shelldata *sd, const char *str)
|
||||
|
||||
void del_cmd(struct shelldata *sd, const char *str)
|
||||
{
|
||||
char key[CW_KTV_MAX_KEY_LEN];
|
||||
char key[CW_CFG_MAX_KEY_LEN];
|
||||
sscanf(str,"%s",key);
|
||||
cw_ktv_del_sub(sd->update_cfg,key);
|
||||
}
|
||||
@ -342,7 +345,7 @@ void execute_cmd (struct shelldata * sd, const char *str)
|
||||
return;
|
||||
|
||||
|
||||
char key[CW_KTV_MAX_KEY_LEN];
|
||||
char key[CW_CFG_MAX_KEY_LEN];
|
||||
char type[128];
|
||||
char val[2048];
|
||||
|
||||
|
@ -37,7 +37,6 @@
|
||||
|
||||
#include "ac.h"
|
||||
#include "conf.h"
|
||||
#include "db.h"
|
||||
#include "socklist.h"
|
||||
#include "wtpman.h"
|
||||
#include "wtplist.h"
|
||||
@ -617,27 +616,49 @@ void wtpman_destroy(struct wtpman *wtpman)
|
||||
{
|
||||
if (wtpman->conn)
|
||||
conn_destroy(wtpman->conn);
|
||||
|
||||
if (wtpman->wtp_cfg)
|
||||
cw_cfg_destroy(wtpman->wtp_cfg);
|
||||
|
||||
free(wtpman);
|
||||
}
|
||||
|
||||
static void discovery_cb(struct cw_ElemHandlerParams * params, uint8_t * elems_ptr, int elems_len)
|
||||
|
||||
static void copy(struct cw_ElemHandlerParams * params)
|
||||
{
|
||||
cw_dbg(DBG_X,"Discovery->Callback");
|
||||
struct wtpman * wtpman;
|
||||
wtpman = (struct wtpman*)params->conn->data;
|
||||
|
||||
cw_dbg(DBG_X,"------------- Here is the config we ve got from WTP ---------------- ");
|
||||
cw_cfg_dump(params->cfg);
|
||||
cw_dbg(DBG_X,"------------- This was the config we ve got from WTP ---------------- ");
|
||||
cw_dbg(DBG_X,"Now copying:");
|
||||
cw_cfg_copy(params->cfg,wtpman->wtp_cfg);
|
||||
cw_dbg(DBG_X,"Copying done.");
|
||||
}
|
||||
|
||||
static void join_cb(struct cw_ElemHandlerParams * params, uint8_t * elems_ptr, int elems_len)
|
||||
static int discovery_cb(struct cw_ElemHandlerParams * params, uint8_t * elems_ptr, int elems_len)
|
||||
{
|
||||
struct wtpman * wtpman = (struct wtpman *)params->conn->data;
|
||||
cw_dbg(DBG_X,"JOIN->Callback");
|
||||
wtpman->pjoin(params,elems_ptr,elems_len);
|
||||
cw_dbg(DBG_X,"DISCOVERY Callback");
|
||||
copy(params);
|
||||
cw_cfg_clear(params->cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_cb(struct cw_ElemHandlerParams * params, uint8_t * elems_ptr, int elems_len)
|
||||
static int join_cb(struct cw_ElemHandlerParams * params, uint8_t * elems_ptr, int elems_len)
|
||||
{
|
||||
struct wtpman * wtpman = (struct wtpman *)params->conn->data;
|
||||
cw_dbg(DBG_X,"UPDATE->Callback");
|
||||
if ( wtpman->pupdate )
|
||||
wtpman->pupdate(params,elems_ptr,elems_len);
|
||||
cw_dbg(DBG_X,"JOIN Callback");
|
||||
copy(params);
|
||||
cw_cfg_clear(params->cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int update_cb(struct cw_ElemHandlerParams * params, uint8_t * elems_ptr, int elems_len)
|
||||
{
|
||||
cw_dbg(DBG_X,"UPDATE Callback");
|
||||
copy(params);
|
||||
cw_cfg_clear(params->cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -646,8 +667,8 @@ static void update_cb(struct cw_ElemHandlerParams * params, uint8_t * elems_ptr,
|
||||
static setup_complete(struct cw_Conn *conn)
|
||||
{
|
||||
struct wtpman * wtpman = (struct wtpman *)conn->data;
|
||||
wtpman->pjoin = cw_msgset_set_postprocess(conn->msgset,CAPWAP_MSG_JOIN_REQUEST,join_cb);
|
||||
wtpman->pupdate = cw_msgset_set_postprocess(conn->msgset,CAPWAP_MSG_CONFIGURATION_STATUS_REQUEST,update_cb);
|
||||
// wtpman->pjoin = cw_msgset_set_postprocess(conn->msgset,CAPWAP_MSG_JOIN_REQUEST,join_cb);
|
||||
// wtpman->pupdate = cw_msgset_set_postprocess(conn->msgset,CAPWAP_MSG_CONFIGURATION_STATUS_REQUEST,update_cb);
|
||||
cw_dbg(DBG_X,"SETUP COMPLETE");
|
||||
|
||||
}
|
||||
@ -704,6 +725,8 @@ struct wtpman *wtpman_create(int socklistindex, struct sockaddr *srcaddr,
|
||||
}
|
||||
wtpman->conn->global_cfg = global_cfg;
|
||||
wtpman->conn->local_cfg = cw_cfg_create();
|
||||
wtpman->wtp_cfg = cw_cfg_create();
|
||||
|
||||
|
||||
wtpman->conn->role = CW_ROLE_AC;
|
||||
wtpman->conn->data=wtpman;
|
||||
@ -716,6 +739,17 @@ struct wtpman *wtpman_create(int socklistindex, struct sockaddr *srcaddr,
|
||||
CAPWAP_MSG_DISCOVERY_REQUEST,
|
||||
discovery_cb);
|
||||
|
||||
cw_conn_set_msg_cb(wtpman->conn,
|
||||
CAPWAP_MSG_JOIN_REQUEST,
|
||||
join_cb);
|
||||
|
||||
cw_conn_set_msg_cb(wtpman->conn,
|
||||
CAPWAP_MSG_CONFIGURATION_STATUS_REQUEST,
|
||||
update_cb);
|
||||
|
||||
|
||||
|
||||
|
||||
// wtpman->conn->mods = conf_mods;
|
||||
|
||||
wtpman->conn->strict_capwap = conf_strict_capwap;
|
||||
@ -764,7 +798,7 @@ struct wtpman *wtpman_create(int socklistindex, struct sockaddr *srcaddr,
|
||||
|
||||
void wtpman_addpacket(struct wtpman *wtpman, uint8_t * packet, int len)
|
||||
{
|
||||
cw_dbg(DBG_X,"ADD PACKET DETECTED %d",wtpman->conn->detected);
|
||||
// cw_dbg(DBG_X,"ADD PACKET DETECTED %d",wtpman->conn->detected);
|
||||
conn_q_add_packet(wtpman->conn, packet, len);
|
||||
}
|
||||
|
||||
|
@ -38,12 +38,9 @@ struct wtpman {
|
||||
from a .ckv file on startup.
|
||||
*/
|
||||
|
||||
cw_Cfg_t * wtp_cfg;
|
||||
|
||||
cw_MsgCallbackFun pdiscovery;
|
||||
cw_MsgCallbackFun pjoin;
|
||||
cw_MsgCallbackFun pupdate;
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
@ -3,6 +3,7 @@ MFDEPS=../Defs.mak
|
||||
|
||||
|
||||
CWSRC=\
|
||||
cw.c\
|
||||
cw_check_missing_mand.c\
|
||||
cw_clock_lap.c\
|
||||
cw_dbg_elem.c\
|
||||
@ -16,12 +17,6 @@ CWSRC=\
|
||||
cw_in_ac_name_with_priority.c\
|
||||
cw_in_capwap_local_ipv4_address.c\
|
||||
cw_in_capwap_local_ipv6_address.c\
|
||||
cw_in_check_disc_req.c\
|
||||
cw_in_check_img_data_req_ac.c\
|
||||
cw_in_check_img_data_req_wtp.c\
|
||||
cw_in_check_join_req.c\
|
||||
cw_in_check_join_resp.c\
|
||||
cw_in_generic.c\
|
||||
cw_in_generic_with_index.c\
|
||||
cw_in_generic_struct.c\
|
||||
cw_in_radio_generic_struct.c\
|
||||
@ -37,7 +32,6 @@ CWSRC=\
|
||||
cw_in_wtp_reboot_statistics.c\
|
||||
cw_is_printable.c\
|
||||
cw_load_file.c\
|
||||
cw_out_generic.c\
|
||||
cw_out_generic_with_index.c\
|
||||
cw_out_radio_administrative_states.c\
|
||||
cw_process_element.c\
|
||||
@ -75,6 +69,14 @@ CWSRC=\
|
||||
cw_detect_nat.c\
|
||||
cw_read_from.c \
|
||||
|
||||
# cw_in_check_disc_req.c\
|
||||
# cw_in_check_img_data_req_ac.c\
|
||||
# cw_in_check_img_data_req_wtp.c\
|
||||
# cw_in_check_join_req.c\
|
||||
# cw_in_check_join_resp.c\
|
||||
# cw_in_generic.c\
|
||||
# cw_out_generic.c\
|
||||
|
||||
KTVSRC=\
|
||||
cw_ktv_add.c\
|
||||
cw_ktv_cast.c\
|
||||
@ -103,9 +105,9 @@ KTVSRC=\
|
||||
cw_ktv_base_exists.c\
|
||||
cw_ktv_save.c\
|
||||
cw_ktv_del_sub.c\
|
||||
cw_ktv_parser.c\
|
||||
cfg.c\
|
||||
|
||||
# cw_ktv_parser.c\
|
||||
|
||||
LWSRC=\
|
||||
lw_addelem.c\
|
||||
@ -179,7 +181,6 @@ MISCSRC=\
|
||||
conn_destroy.c\
|
||||
connlist.c\
|
||||
conn_prepare_image_data_request.c\
|
||||
conn_process_packet.c\
|
||||
cw_decode_msg.c \
|
||||
conn_q_add_packet.c\
|
||||
conn_q_get_packet.c\
|
||||
@ -200,13 +201,15 @@ MISCSRC=\
|
||||
send.c\
|
||||
strheap.c\
|
||||
netconn.c\
|
||||
conn.c
|
||||
conn.c \
|
||||
val.c
|
||||
|
||||
# conn_q_wait_packet.c\
|
||||
# conn_init.c\
|
||||
# conn_create.c\
|
||||
# conn_send_request.c\
|
||||
# cw_put_msg.c\
|
||||
# conn_process_packet.c\
|
||||
|
||||
DTLSSRC+=\
|
||||
dtls_bio.c\
|
||||
@ -216,7 +219,7 @@ DTLSSRC+=\
|
||||
RADIOSRC=\
|
||||
cw_out_radio_generic.c\
|
||||
cw_out_radio_generic_struct.c\
|
||||
cw_read_radio_generic.c\
|
||||
cw_in_radio_generic.c\
|
||||
|
||||
MAVLSRC=\
|
||||
mavl_get_ptr.c\
|
||||
|
83
src/cw/cfg.c
83
src/cw/cfg.c
@ -122,6 +122,20 @@ const char *cw_cfg_get(cw_Cfg_t * cfg, const char *key, const char *def)
|
||||
return r->val;
|
||||
}
|
||||
|
||||
const char *cw_cfg_get_l(cw_Cfg_t ** cfg, const char * key, const char *def)
|
||||
{
|
||||
int i;
|
||||
struct cw_Cfg_entry e, *r;
|
||||
for(i=0; cfg[i]!=NULL; i++){
|
||||
e.key = key;
|
||||
r = mavl_get(cfg[i], &e);
|
||||
if (r!=NULL)
|
||||
return r->val;
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
|
||||
const char *cw_cfg_get2(cw_Cfg_t *cfg1, cw_Cfg_t *cfg2, const char *key, const char *def)
|
||||
{
|
||||
return cw_cfg_get(cfg1, key, cw_cfg_get(cfg2,key,def));
|
||||
@ -527,7 +541,7 @@ uint8_t cw_cfg_get_byte(cw_Cfg_t * cfg, char *key, uint8_t def)
|
||||
if (s==NULL)
|
||||
return def;
|
||||
CW_TYPE_BYTE->from_str(&v,s);
|
||||
return v.val.word;
|
||||
return v.val.byte;
|
||||
}
|
||||
|
||||
|
||||
@ -596,7 +610,6 @@ int cw_cfg_set_val(cw_Cfg_t * cfg, const char *key, const struct cw_Type *type,
|
||||
memset(&mdata,0,sizeof(cw_Val_t));
|
||||
mdata.type=type;
|
||||
mdata.valguard=valguard;
|
||||
cw_dbg(DBG_X,"SETVAL FOR TYPE: %s",type->name);
|
||||
mresult = type->get(&mdata,data,len);
|
||||
if (!mresult){
|
||||
cw_log(LOG_ERR, "Can't create cfg element for key %s of type %s: %s",
|
||||
@ -611,3 +624,69 @@ cw_dbg(DBG_X,"SETVAL FOR TYPE: %s",type->name);
|
||||
type->del(&mdata);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void cw_cfg_copy(cw_Cfg_t *src, cw_Cfg_t *dst)
|
||||
{
|
||||
mavliter_t it;
|
||||
mavliter_init(&it, src);
|
||||
mavliter_foreach(&it) {
|
||||
int exists;
|
||||
struct cw_Cfg_entry * old_elem,*e, new_elem;
|
||||
|
||||
e = mavliter_get(&it);
|
||||
new_elem.key = cw_strdup(e->key);
|
||||
new_elem.val = cw_strdup(e->val);
|
||||
|
||||
old_elem = mavl_insert(dst,&new_elem,&exists);
|
||||
if (!exists){
|
||||
cw_dbg(DBG_X, "New: %s: %s",new_elem.key,new_elem.val);
|
||||
continue;
|
||||
}
|
||||
if (strcmp(new_elem.val,old_elem->val)==0){
|
||||
free((void*)new_elem.key);
|
||||
free((void*)new_elem.val);
|
||||
continue;
|
||||
}
|
||||
|
||||
cw_dbg(DBG_X, "Replace: %s: %s (old: %s)",new_elem.key, new_elem.val, old_elem->val);
|
||||
if(dst->del){
|
||||
dst->del(old_elem);
|
||||
}
|
||||
memcpy(old_elem,&new_elem,dst->data_size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void cw_cfg_destroy(cw_Cfg_t *cfg)
|
||||
{
|
||||
mavl_destroy(cfg);
|
||||
}
|
||||
|
||||
|
||||
void cw_cfg_clear(cw_Cfg_t *cfg)
|
||||
{
|
||||
mavl_del_all(cfg);
|
||||
}
|
||||
|
||||
|
||||
int cw_cfg_base_exists(cw_Cfg_t * cfg, const char *key)
|
||||
{
|
||||
struct cw_Cfg_entry e, *result;
|
||||
|
||||
e.key=key;
|
||||
result = mavl_get_first(cfg,&e);
|
||||
if (result == NULL)
|
||||
return 0;
|
||||
|
||||
if (strlen(result->key)<strlen(key))
|
||||
return 0;
|
||||
if (result->key[strlen(key)]!='/' && result->key[strlen(key)]!='.')
|
||||
return 0;
|
||||
if (strncmp(result->key,key,strlen(key))==0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -38,6 +38,14 @@ uint8_t cw_cfg_get_byte(cw_Cfg_t * cfg, char *key, uint8_t def);
|
||||
bstr16_t cw_cfg_get_bstr16(cw_Cfg_t * cfg, const char * key, const char *def);
|
||||
int cw_cfg_set_bstr16(cw_Cfg_t * cfg, const char * key, bstr16_t str);
|
||||
int cw_cfg_get_next_index(cw_Cfg_t * cfg, const char *key);
|
||||
const char *cw_cfg_get_l(cw_Cfg_t ** cfg, const char * key, const char *def);
|
||||
void cw_cfg_copy(cw_Cfg_t *src, cw_Cfg_t *dst);
|
||||
void cw_cfg_destroy(cw_Cfg_t *cfg);
|
||||
void cw_cfg_clear(cw_Cfg_t *cfg);
|
||||
int cw_cfg_base_exists(cw_Cfg_t * cfg, const char *key);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cw_cfg_set_val(cw_Cfg_t * cfg, const char *key, const struct cw_Type *t, const void * valguard, const uint8_t * data, int len);
|
||||
|
668
src/cw/conn.c
668
src/cw/conn.c
@ -40,9 +40,6 @@ int cw_assemble_message(struct cw_Conn *conn, uint8_t * rawout)
|
||||
struct mlistelem * elem;
|
||||
int len,l;
|
||||
|
||||
//cw_dbg(DBG_INFO, "Number of elements in ktv: %d",conn->local_cfg->count);
|
||||
/* cw_dbg_ktv_dump(conn->local_cfg,DBG_CFG_DMP,"Local CFG","LOCAL:","End Local CFG");*/
|
||||
|
||||
/* rawout is already initialized, so we can get
|
||||
* msg type from buffer */
|
||||
msgptr = rawout + cw_get_hdr_msg_offset(rawout);
|
||||
@ -72,7 +69,7 @@ int cw_assemble_message(struct cw_Conn *conn, uint8_t * rawout)
|
||||
|
||||
data = mlistelem_dataptr(elem);
|
||||
handler = cw_msgset_get_elemhandler(conn->msgset,data->proto,data->vendor,data->id);
|
||||
// cw_dbg(DBG_X,"Elem: %d %d %d %s\n", data->proto, data->vendor, data->id, handler->name);
|
||||
cw_dbg(DBG_MSG_ASSEMBLY," Add Elem: %d %d %d %s", data->proto, data->vendor, data->id, handler->name);
|
||||
if (handler==NULL){
|
||||
cw_log(LOG_ERR,"Can't put message element %d %d %d, no handler defined.",
|
||||
data->proto,data->vendor,data->id);
|
||||
@ -91,7 +88,11 @@ int cw_assemble_message(struct cw_Conn *conn, uint8_t * rawout)
|
||||
|
||||
params.conn=conn;
|
||||
params.cfg=conn->remote_cfg;
|
||||
params.default_cfg=conn->default_cfg;
|
||||
params.cfg_list[0]=params.cfg;
|
||||
params.cfg_list[1]=conn->local_cfg;
|
||||
params.cfg_list[2]=conn->global_cfg;
|
||||
params.cfg_list[3]=NULL;
|
||||
|
||||
|
||||
params.msgset=conn->msgset;
|
||||
|
||||
@ -106,8 +107,14 @@ int cw_assemble_message(struct cw_Conn *conn, uint8_t * rawout)
|
||||
printf("flash config\n");
|
||||
cisco/ap-led-flash-config/flash-enable
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
if (!data->mand){
|
||||
if (!cw_cfg_base_exists(params.cfg,handler->key)){
|
||||
cw_dbg(DBG_X,"nothing todo");
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
l = handler->put(handler,¶ms,dst+len);
|
||||
|
||||
|
||||
@ -138,12 +145,11 @@ int cw_assemble_message(struct cw_Conn *conn, uint8_t * rawout)
|
||||
uint8_t *msg_ptr = rawout + offset;
|
||||
int elems_len = cw_get_msg_elems_len(msg_ptr);
|
||||
elems_ptr = cw_get_msg_elems_ptr(msg_ptr);
|
||||
mavl_t * cfg = cw_cfg_create();
|
||||
cw_Cfg_t * cfg = cw_cfg_create();
|
||||
|
||||
struct cw_ElemHandlerParams params;
|
||||
|
||||
params.cfg=cfg;
|
||||
params.default_cfg=NULL;
|
||||
params.msgset=conn->msgset;
|
||||
params.msgdata=msg;
|
||||
|
||||
@ -202,6 +208,7 @@ int cw_conn_set_msg_cb(struct cw_Conn *conn, int type, cw_MsgCallbackFun fun)
|
||||
cb.type = type;
|
||||
cb.fun = fun;
|
||||
mavl_insert(conn->msg_callbacks,&cb,&exists);
|
||||
return 1;
|
||||
}
|
||||
|
||||
cw_MsgCallbackFun cw_conn_get_msg_cb(struct cw_Conn *conn, int type)
|
||||
@ -288,3 +295,646 @@ struct cw_Conn * cw_conn_create(int sock, struct sockaddr * addr, int qsize)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Init response message header
|
||||
*/
|
||||
void cw_init_response(struct cw_Conn *conn, uint8_t * req)
|
||||
{
|
||||
uint8_t *buffer;
|
||||
int shbytes, dhbytes;
|
||||
uint8_t *msgptr, *dmsgptr;
|
||||
|
||||
buffer = conn->resp_buffer;
|
||||
shbytes = cw_get_hdr_msg_offset(req);
|
||||
|
||||
memcpy(buffer, req, shbytes);
|
||||
|
||||
cw_set_hdr_rmac(buffer, conn->base_rmac);
|
||||
/*
|
||||
// cw_set_hdr_hlen(buffer, 2);
|
||||
// cw_set_hdr_flags(buffer, CW_FLAG_HDR_M, 1);
|
||||
*/
|
||||
|
||||
dhbytes = cw_get_hdr_msg_offset(buffer);
|
||||
|
||||
msgptr = req + shbytes;
|
||||
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 cw_Conn *conn, int msg_id)
|
||||
{
|
||||
uint8_t *buffer = conn->req_buffer;
|
||||
uint8_t *msgptr;
|
||||
|
||||
/* zero the first 8 bytes */
|
||||
cw_set_dword(buffer + 0, 0);
|
||||
cw_set_dword(buffer + 4, 0);
|
||||
|
||||
/* unencrypted */
|
||||
cw_set_hdr_preamble(buffer, CAPWAP_VERSION << 4 | 0);
|
||||
|
||||
cw_set_hdr_rmac(buffer, conn->base_rmac);
|
||||
/*
|
||||
//cw_set_hdr_hlen(buffer, 2);
|
||||
*/
|
||||
|
||||
|
||||
cw_set_hdr_wbid(buffer, conn->wbid);
|
||||
cw_set_hdr_rid(buffer, 0);
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void cw_init_data_msg(struct cw_Conn *conn)
|
||||
{
|
||||
uint8_t *buffer = conn->req_buffer;
|
||||
cw_set_dword(buffer + 0, 0);
|
||||
cw_set_dword(buffer + 4, 0);
|
||||
|
||||
/* unencrypted */
|
||||
cw_set_hdr_preamble(buffer, CAPWAP_VERSION << 4 | 0);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* send a response
|
||||
*/
|
||||
int cw_send_response(struct cw_Conn *conn, uint8_t * rawmsg, int len)
|
||||
{
|
||||
int rc;
|
||||
cw_init_response(conn, rawmsg);
|
||||
rc = cw_assemble_message(conn, conn->resp_buffer);
|
||||
if (!cw_result_is_ok(rc))
|
||||
return 0;
|
||||
conn_send_msg(conn, conn->resp_buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Special case error message, which is sent when an unexpected messages
|
||||
* was received or something else happened.
|
||||
* @param conn conection
|
||||
* @param rawmsg the received request message, which the response belongs to
|
||||
* @param result_code result code to send
|
||||
* @return 1
|
||||
*/
|
||||
int cw_send_error_response(struct cw_Conn *conn, uint8_t * rawmsg,
|
||||
uint32_t result_code)
|
||||
{
|
||||
uint8_t *out, *dst;
|
||||
int l;
|
||||
|
||||
cw_init_response(conn, rawmsg);
|
||||
|
||||
out = conn->resp_buffer;
|
||||
|
||||
dst = cw_get_hdr_msg_elems_ptr(out);
|
||||
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 struct cw_MsgSet *load_msg_set(struct cw_Conn *conn, uint8_t * rawmsg,
|
||||
int len, int elems_len,
|
||||
struct sockaddr *from)
|
||||
{
|
||||
char sock_buf[SOCK_ADDR_BUFSIZE];
|
||||
struct cw_Mod *cmod, *bmod;
|
||||
|
||||
cmod =
|
||||
cw_mod_detect(conn, rawmsg, len, elems_len, from,
|
||||
CW_MOD_MODE_CAPWAP);
|
||||
if (cmod == MOD_NULL) {
|
||||
cw_dbg(DBG_MSG_ERR,
|
||||
"Can't find mod to handle connection from %s, discarding message",
|
||||
sock_addr2str_p(from, sock_buf));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bmod =
|
||||
cw_mod_detect(conn, rawmsg, len, elems_len, from,
|
||||
CW_MOD_MODE_BINDINGS);
|
||||
|
||||
|
||||
cw_dbg(DBG_INFO, "Mods deteced: %s,%s", cmod->name, bmod->name);
|
||||
|
||||
conn->cmod = cmod;
|
||||
conn->bmod = bmod;
|
||||
|
||||
return cw_mod_get_msg_set(conn, cmod, bmod);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
int cw_in_check_generic(struct cw_Conn *conn, struct cw_action_in *a, uint8_t * data,
|
||||
int len,struct sockaddr *from)
|
||||
{
|
||||
// if (cw_is_request(a->msg_id)){
|
||||
// return cw_in_check_generic_req(conn,a,data,len,from);
|
||||
// }
|
||||
// return cw_in_check_generic_resp(conn,a,data,len,from);
|
||||
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
void cw_read_elem(struct cw_ElemHandler * handler, struct cw_Conn * conn,
|
||||
uint8_t * elem_data, int elem_len, struct sockaddr * from){
|
||||
mavldata_t data, *result;
|
||||
char str[30];
|
||||
|
||||
result = handler->type->get(&data,elem_data,elem_len);
|
||||
|
||||
handler->type->to_str(result,str,30);
|
||||
printf("Read %d-%s: %s %s\n", handler->id, handler->name, handler->key, str);
|
||||
//mavl_insert(conn->remote_cfg
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static int process_elements(struct cw_Conn *conn, uint8_t * rawmsg, int len,
|
||||
struct sockaddr *from)
|
||||
{
|
||||
mavl_t mand_found;
|
||||
mlist_t unrecognized;
|
||||
struct cw_MsgData search;
|
||||
struct cw_MsgData *message;
|
||||
int result_code;
|
||||
cw_State_t *ui;
|
||||
|
||||
uint8_t *elems_ptr;
|
||||
struct cw_ElemHandlerParams params;
|
||||
|
||||
char sock_buf[SOCK_ADDR_BUFSIZE]; /**< to hold str from sockaddr2str */
|
||||
|
||||
/*struct cw_action_in as, *af, *afm; */
|
||||
|
||||
int offset = cw_get_hdr_msg_offset(rawmsg);
|
||||
|
||||
uint8_t *msg_ptr = rawmsg + offset;
|
||||
|
||||
int elems_len = cw_get_msg_elems_len(msg_ptr);
|
||||
|
||||
int payloadlen = len - offset;
|
||||
|
||||
|
||||
/* pre-check message */
|
||||
if (payloadlen - 8 != elems_len) {
|
||||
|
||||
if (conn->strict_hdr) {
|
||||
cw_dbg(DBG_MSG_ERR,
|
||||
"Discarding message from %s, msgelems len=%d, payload len=%d, (Strict CAPWAP) ",
|
||||
sock_addr2str(&conn->addr, sock_buf), elems_len,
|
||||
payloadlen - 8);
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (elems_len < payloadlen - 8) {
|
||||
cw_dbg(DBG_RFC,
|
||||
"Packet from from %s has %d bytes of extra data, ignoring.",
|
||||
sock_addr2str(&conn->addr, sock_buf),
|
||||
payloadlen - 8 - elems_len);
|
||||
elems_len = len - 8;
|
||||
}
|
||||
|
||||
if (elems_len > payloadlen - 8) {
|
||||
|
||||
cw_dbg(DBG_RFC,
|
||||
"Packet from from %s has msgelems len of %d bytes, but has only %d bytes of data, truncating.",
|
||||
sock_addr2str(&conn->addr, sock_buf), elems_len,
|
||||
payloadlen - 8);
|
||||
elems_len = payloadlen - 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Detect the connecting WTP type */
|
||||
if (!conn->detected) {
|
||||
|
||||
struct cw_MsgSet *set =
|
||||
load_msg_set(conn, rawmsg, len, elems_len, from);
|
||||
if (!set) {
|
||||
/*
|
||||
//cw_log(LOG_ERR, "Error");
|
||||
*/
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
conn->cmod->setup_cfg(conn);
|
||||
conn->msgset = set;
|
||||
conn->detected = 1;
|
||||
|
||||
if (conn->setup_complete)
|
||||
conn->setup_complete(conn);
|
||||
|
||||
}
|
||||
|
||||
/** debug the received message */
|
||||
cw_dbg_msg(DBG_MSG_IN, conn, rawmsg, len, from);
|
||||
|
||||
/* prepare struct for search operation */
|
||||
search.type = cw_get_msg_id(msg_ptr);
|
||||
|
||||
/* Search message */
|
||||
|
||||
message = mavl_get(conn->msgset->msgdata, &search);
|
||||
|
||||
result_code = 0;
|
||||
|
||||
if (!message) {
|
||||
/* Message is unknown */
|
||||
if (search.type & 1) {
|
||||
cw_dbg(DBG_MSG_ERR,
|
||||
"Message type %d [%s] unrecognized, sending response.",
|
||||
search.type, cw_strmsg(search.type),
|
||||
cw_strstate(conn->capwap_state));
|
||||
|
||||
result_code = CAPWAP_RESULT_MSG_UNRECOGNIZED;
|
||||
cw_send_error_response(conn, rawmsg, result_code);
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
cw_dbg(DBG_MSG_ERR,
|
||||
"Message type %d [%s] unrecognized, discarding.",
|
||||
search.type, cw_strmsg(search.type),
|
||||
cw_strstate(conn->capwap_state));
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/* Throw away unexpected messages */
|
||||
/* maybe we have to check this too: if (!(message->type & 1))
|
||||
* means unexpected response message
|
||||
* */
|
||||
if (!(message->receiver & conn->role)) {
|
||||
cw_dbg(DBG_MSG_ERR,
|
||||
"Message type %d (%s) unexpected/illegal in %s State, discarding.",
|
||||
search.type, cw_strmsg(search.type),
|
||||
cw_strstate(conn->capwap_state));
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if current state is in state of message */
|
||||
ui = message->states;
|
||||
|
||||
for (ui = message->states; ui->state; ui++) {
|
||||
/* printf("Comparing %d and %d\n", conn->capwap_state, ui->state);*/
|
||||
if (ui->state == conn->capwap_state) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ui->state) {
|
||||
/* Message found, but it was in wrong state */
|
||||
cw_dbg(DBG_MSG_ERR,
|
||||
"Message type %d (%s) not allowed in %s State, sending response.",
|
||||
search.type, cw_strmsg(search.type),
|
||||
cw_strstate(conn->capwap_state));
|
||||
result_code = CAPWAP_RESULT_MSG_INVALID_IN_CURRENT_STATE;
|
||||
cw_send_error_response(conn, rawmsg, result_code);
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
elems_ptr = cw_get_msg_elems_ptr(msg_ptr);
|
||||
|
||||
|
||||
|
||||
mand_found = mavl_create_conststr();
|
||||
unrecognized = mlist_create(NULL, NULL, sizeof(uint8_t *));
|
||||
|
||||
|
||||
|
||||
|
||||
cw_dbg(DBG_MSG_PARSING, "*** Parsing message of type %d - (%s) ***",
|
||||
message->type, message->name);
|
||||
|
||||
params.cfg = cw_cfg_create(); //conn->remote_cfg;
|
||||
params.cfg_list[0]=params.cfg;
|
||||
params.cfg_list[1]=conn->local_cfg;
|
||||
params.cfg_list[2]=conn->global_cfg;
|
||||
params.cfg_list[3]=NULL;
|
||||
|
||||
params.from = from;
|
||||
params.msgdata = message;
|
||||
params.mand_found = mand_found;
|
||||
params.msgset=conn->msgset;
|
||||
params.conn = conn;
|
||||
|
||||
cw_decode_elements(¶ms,elems_ptr, elems_len);
|
||||
|
||||
/* all message elements are processed, do now after processing
|
||||
by calling the "end" function for the message */
|
||||
|
||||
cw_check_missing_mand(message, mand_found);
|
||||
|
||||
cw_dbg(DBG_MSG_PARSING, "*** End parsing message of type %d (%s) ***",
|
||||
message->type, message->name);
|
||||
|
||||
|
||||
mavl_destroy(mand_found);
|
||||
|
||||
if (message->postprocess) {
|
||||
message->postprocess(¶ms,elems_ptr, elems_len);
|
||||
}
|
||||
|
||||
cw_MsgCallbackFun cb_fun = cw_conn_get_msg_cb(conn,message->type);
|
||||
if (cb_fun != NULL){
|
||||
result_code = cb_fun(¶ms,elems_ptr, elems_len);
|
||||
}
|
||||
else{
|
||||
cw_cfg_clear(params.cfg);
|
||||
}
|
||||
|
||||
conn->remote_cfg=params.cfg;
|
||||
|
||||
/* if we've got a request message, we always have to send a response message */
|
||||
if (message->type & 1) {
|
||||
if (result_code > 0) {
|
||||
/* the end method gave us an result code>0, so
|
||||
send an error message */
|
||||
|
||||
cw_send_error_response(conn, rawmsg, result_code);
|
||||
} else if (result_code == 0) {
|
||||
cw_cfg_set_int(params.cfg, "result-code",
|
||||
result_code);
|
||||
if (ui->next) {
|
||||
conn->capwap_prevstate = conn->capwap_state;
|
||||
conn->capwap_state = ui->next;
|
||||
}
|
||||
|
||||
/* All is ok, send regular response message */
|
||||
cw_send_response(conn, rawmsg, len);
|
||||
} else {
|
||||
/* the request message is ignored, no response
|
||||
will be sent */
|
||||
errno = EAGAIN;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Whe have got a response message.
|
||||
* Put further actions here, if needed.
|
||||
*/
|
||||
}
|
||||
cw_cfg_destroy(params.cfg);
|
||||
|
||||
return result_code;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int process_message(struct cw_Conn *conn, uint8_t * rawmsg, int rawlen,
|
||||
struct sockaddr *from)
|
||||
{
|
||||
char sock_buf[SOCK_ADDR_BUFSIZE];
|
||||
uint8_t seqnum;
|
||||
int s1, s2, sd;
|
||||
|
||||
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. */
|
||||
return process_elements(conn, rawmsg, rawlen, from);
|
||||
}
|
||||
|
||||
/* It's a request message, check if seqnum is right and if
|
||||
* we have already sent a response message*/
|
||||
|
||||
seqnum = cw_get_msg_seqnum(msgptr);
|
||||
|
||||
s1 = conn->last_seqnum_received;
|
||||
s2 = seqnum;
|
||||
sd = s2 - s1;
|
||||
|
||||
if ((sd > 0 && sd < 128) || (sd < 0 && sd < -128) || s1 < 0) {
|
||||
/* seqnum is ok, normal message processing */
|
||||
conn->last_seqnum_received = seqnum;
|
||||
|
||||
return process_elements(conn, rawmsg, rawlen, from);
|
||||
}
|
||||
|
||||
if (sd != 0) {
|
||||
cw_dbg(DBG_MSG_ERR,
|
||||
"Discarding message from %s, old seqnum, seqnum = %d, last seqnum=%d",
|
||||
sock_addr2str(&conn->addr, sock_buf), s2, s1);
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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, sock_buf), s2, type);
|
||||
|
||||
|
||||
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, sock_buf), s2);
|
||||
|
||||
/*// XXX untested */
|
||||
conn_send_msg(conn, conn->resp_buffer);
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process an incomming CAPWAP packet, assuming the packet is already decrypted
|
||||
* @param conn conection object
|
||||
* @param packet pointer to packet data
|
||||
* @param len lenght of packet data
|
||||
*/
|
||||
int conn_process_packet2(struct cw_Conn *conn, uint8_t * packet, int len,
|
||||
struct sockaddr *from)
|
||||
{
|
||||
char sock_buf[SOCK_ADDR_BUFSIZE];
|
||||
int preamble;
|
||||
int offs;
|
||||
int payloadlen;
|
||||
|
||||
if (len < 8) {
|
||||
/* packet too short */
|
||||
cw_dbg(DBG_PKT_ERR,
|
||||
"Discarding packet from %s, packet too short, len=%d, at least 8 expected.",
|
||||
sock_addr2str(&conn->addr, sock_buf), len);
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
preamble = cw_get_hdr_preamble(packet);
|
||||
|
||||
if ((preamble & 0xf0) != (CAPWAP_VERSION << 4)) {
|
||||
/* wrong version */
|
||||
cw_dbg(DBG_PKT_ERR,
|
||||
"Discarding packet from %s, wrong version, version=%d, version %d expected.",
|
||||
sock_addr2str(&conn->addr, sock_buf),
|
||||
(preamble & 0xf0) >> 4, CAPWAP_VERSION);
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (preamble & 0xf) {
|
||||
/* Encrypted data, this shuold never happen here */
|
||||
cw_dbg(DBG_PKT_ERR,
|
||||
"Discarding packet from %s, encrypted data after decryption ...",
|
||||
sock_addr2str(&conn->addr, sock_buf));
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
offs = cw_get_hdr_msg_offset(packet);
|
||||
|
||||
|
||||
payloadlen = len - offs;
|
||||
if (payloadlen < 0) {
|
||||
/* Eleminate messages with wrong header size */
|
||||
cw_dbg(DBG_PKT_ERR,
|
||||
"Discarding packet from %s, header length (%d) greater than packet len (%d).",
|
||||
sock_addr2str(&conn->addr, sock_buf), offs, len);
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if Radio MAC is present */
|
||||
if (cw_get_hdr_flag_m(packet)) {
|
||||
|
||||
if (cw_get_hdr_rmac_len(packet) + 8 > offs) {
|
||||
/* wrong rmac size */
|
||||
cw_dbg(DBG_PKT_ERR,
|
||||
"Discarding packet from %s, wrong R-MAC size, size=%d",
|
||||
sock_addr2str(&conn->addr, sock_buf),
|
||||
*(packet + 8));
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (cw_get_hdr_flag_f(packet)) {
|
||||
/* fragmented, add the packet to fragman */
|
||||
uint8_t *f;
|
||||
int rc;
|
||||
|
||||
f = fragman_add(conn->fragman, packet, offs, payloadlen);
|
||||
if (f == NULL) {
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
cw_dbg_pkt(DBG_PKT_IN, conn, f + 4, *(uint32_t *) f, from);
|
||||
/*// cw_dbg_msg(DBG_MSG_IN, conn, f + 4, *(uint32_t *) f, from);*/
|
||||
|
||||
/* // XXX: Modify fragman to not throw away CAPWAP headers*/
|
||||
|
||||
rc = conn->process_message(conn, f + 4, *(uint32_t *) f, from);
|
||||
|
||||
free(f);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* not fragmented, we have a complete message */
|
||||
/*// cw_dbg_msg(DBG_MSG_IN, conn, packet, len, from);*/
|
||||
return conn->process_message(conn, packet, len, from);
|
||||
}
|
||||
|
||||
int conn_process_packet(struct cw_Conn *conn, uint8_t * packet, int len,
|
||||
struct sockaddr *from)
|
||||
{
|
||||
|
||||
/* show this packet in debug output */
|
||||
cw_dbg_pkt(DBG_PKT_IN, conn, packet, len, from);
|
||||
|
||||
return conn_process_packet2(conn, packet, len, from);
|
||||
}
|
||||
|
||||
|
||||
int conn_process_data_packet(struct cw_Conn *conn, uint8_t * packet, int len,
|
||||
struct sockaddr *from)
|
||||
{
|
||||
|
||||
/* show this packet in debug output */
|
||||
cw_dbg_pkt(DBG_PKT_IN, conn, packet, len, from);
|
||||
|
||||
return conn_process_packet2(conn, packet, len, from);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Used as main message loop
|
||||
*/
|
||||
int cw_read_messages(struct cw_Conn *conn)
|
||||
{
|
||||
uint8_t buf[2024];
|
||||
int len = 2024;
|
||||
|
||||
int n = conn->read(conn, buf, len);
|
||||
if (n < 0)
|
||||
return n;
|
||||
|
||||
if (n > 0) {
|
||||
return conn->process_packet(conn, buf, n,
|
||||
(struct sockaddr *) &conn->addr);
|
||||
}
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
@ -174,12 +174,12 @@ struct cw_Conn {
|
||||
|
||||
struct cw_Mod *cmod, *bmod;
|
||||
|
||||
char *dtls_cert_file;
|
||||
char *dtls_key_file;
|
||||
char *dtls_key_pass;
|
||||
const char *dtls_cert_file;
|
||||
const char *dtls_key_file;
|
||||
const char *dtls_key_pass;
|
||||
|
||||
void *dtls_data;
|
||||
char *dtls_cipher;
|
||||
const char *dtls_cipher;
|
||||
int dtls_error;
|
||||
|
||||
uint8_t dtls_cookie[8];
|
||||
@ -317,5 +317,10 @@ void conn_clear_upd(struct cw_Conn*conn, int merge);
|
||||
int cw_conn_set_msg_cb(struct cw_Conn *conn, int type, cw_MsgCallbackFun fun);
|
||||
cw_MsgCallbackFun cw_conn_get_msg_cb(struct cw_Conn *conn, int type);
|
||||
|
||||
int cw_decode_element(struct cw_ElemHandlerParams *params, int proto,
|
||||
int vendor, int elem_id, uint8_t * data, int len);
|
||||
|
||||
int cw_decode_elements(struct cw_ElemHandlerParams * params, uint8_t * elems_ptr, int elems_len);
|
||||
|
||||
|
||||
#endif /* __CONN_H */
|
||||
|
@ -38,643 +38,3 @@
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Init response message header
|
||||
*/
|
||||
void cw_init_response(struct cw_Conn *conn, uint8_t * req)
|
||||
{
|
||||
uint8_t *buffer;
|
||||
int shbytes, dhbytes;
|
||||
uint8_t *msgptr, *dmsgptr;
|
||||
|
||||
buffer = conn->resp_buffer;
|
||||
shbytes = cw_get_hdr_msg_offset(req);
|
||||
|
||||
memcpy(buffer, req, shbytes);
|
||||
|
||||
cw_set_hdr_rmac(buffer, conn->base_rmac);
|
||||
/*
|
||||
// cw_set_hdr_hlen(buffer, 2);
|
||||
// cw_set_hdr_flags(buffer, CW_FLAG_HDR_M, 1);
|
||||
*/
|
||||
|
||||
dhbytes = cw_get_hdr_msg_offset(buffer);
|
||||
|
||||
msgptr = req + shbytes;
|
||||
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 cw_Conn *conn, int msg_id)
|
||||
{
|
||||
uint8_t *buffer = conn->req_buffer;
|
||||
uint8_t *msgptr;
|
||||
|
||||
/* zero the first 8 bytes */
|
||||
cw_set_dword(buffer + 0, 0);
|
||||
cw_set_dword(buffer + 4, 0);
|
||||
|
||||
/* unencrypted */
|
||||
cw_set_hdr_preamble(buffer, CAPWAP_VERSION << 4 | 0);
|
||||
|
||||
cw_set_hdr_rmac(buffer, conn->base_rmac);
|
||||
/*
|
||||
//cw_set_hdr_hlen(buffer, 2);
|
||||
*/
|
||||
|
||||
|
||||
cw_set_hdr_wbid(buffer, conn->wbid);
|
||||
cw_set_hdr_rid(buffer, 0);
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void cw_init_data_msg(struct cw_Conn *conn)
|
||||
{
|
||||
uint8_t *buffer = conn->req_buffer;
|
||||
cw_set_dword(buffer + 0, 0);
|
||||
cw_set_dword(buffer + 4, 0);
|
||||
|
||||
/* unencrypted */
|
||||
cw_set_hdr_preamble(buffer, CAPWAP_VERSION << 4 | 0);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* send a response
|
||||
*/
|
||||
int cw_send_response(struct cw_Conn *conn, uint8_t * rawmsg, int len)
|
||||
{
|
||||
int rc;
|
||||
cw_init_response(conn, rawmsg);
|
||||
rc = cw_assemble_message(conn, conn->resp_buffer);
|
||||
if (!cw_result_is_ok(rc))
|
||||
return 0;
|
||||
conn_send_msg(conn, conn->resp_buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Special case error message, which is sent when an unexpected messages
|
||||
* was received or something else happened.
|
||||
* @param conn conection
|
||||
* @param rawmsg the received request message, which the response belongs to
|
||||
* @param result_code result code to send
|
||||
* @return 1
|
||||
*/
|
||||
int cw_send_error_response(struct cw_Conn *conn, uint8_t * rawmsg,
|
||||
uint32_t result_code)
|
||||
{
|
||||
uint8_t *out, *dst;
|
||||
int l;
|
||||
|
||||
cw_init_response(conn, rawmsg);
|
||||
|
||||
out = conn->resp_buffer;
|
||||
|
||||
dst = cw_get_hdr_msg_elems_ptr(out);
|
||||
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 struct cw_MsgSet *load_msg_set(struct cw_Conn *conn, uint8_t * rawmsg,
|
||||
int len, int elems_len,
|
||||
struct sockaddr *from)
|
||||
{
|
||||
char sock_buf[SOCK_ADDR_BUFSIZE];
|
||||
struct cw_Mod *cmod, *bmod;
|
||||
|
||||
cmod =
|
||||
cw_mod_detect(conn, rawmsg, len, elems_len, from,
|
||||
CW_MOD_MODE_CAPWAP);
|
||||
if (cmod == MOD_NULL) {
|
||||
cw_dbg(DBG_MSG_ERR,
|
||||
"Can't find mod to handle connection from %s, discarding message",
|
||||
sock_addr2str_p(from, sock_buf));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bmod =
|
||||
cw_mod_detect(conn, rawmsg, len, elems_len, from,
|
||||
CW_MOD_MODE_BINDINGS);
|
||||
|
||||
|
||||
cw_dbg(DBG_INFO, "Mods deteced: %s,%s", cmod->name, bmod->name);
|
||||
|
||||
conn->cmod = cmod;
|
||||
conn->bmod = bmod;
|
||||
|
||||
return cw_mod_get_msg_set(conn, cmod, bmod);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
int cw_in_check_generic(struct cw_Conn *conn, struct cw_action_in *a, uint8_t * data,
|
||||
int len,struct sockaddr *from)
|
||||
{
|
||||
// if (cw_is_request(a->msg_id)){
|
||||
// return cw_in_check_generic_req(conn,a,data,len,from);
|
||||
// }
|
||||
// return cw_in_check_generic_resp(conn,a,data,len,from);
|
||||
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
void cw_read_elem(struct cw_ElemHandler * handler, struct cw_Conn * conn,
|
||||
uint8_t * elem_data, int elem_len, struct sockaddr * from){
|
||||
mavldata_t data, *result;
|
||||
char str[30];
|
||||
|
||||
result = handler->type->get(&data,elem_data,elem_len);
|
||||
|
||||
handler->type->to_str(result,str,30);
|
||||
printf("Read %d-%s: %s %s\n", handler->id, handler->name, handler->key, str);
|
||||
//mavl_insert(conn->remote_cfg
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static int process_elements(struct cw_Conn *conn, uint8_t * rawmsg, int len,
|
||||
struct sockaddr *from)
|
||||
{
|
||||
mavl_t mand_found;
|
||||
mlist_t unrecognized;
|
||||
struct cw_MsgData search;
|
||||
struct cw_MsgData *message;
|
||||
int result_code;
|
||||
cw_State_t *ui;
|
||||
|
||||
uint8_t *elems_ptr;
|
||||
uint8_t *elem;
|
||||
struct cw_ElemHandlerParams params;
|
||||
|
||||
char sock_buf[SOCK_ADDR_BUFSIZE]; /**< to hold str from sockaddr2str */
|
||||
|
||||
/*struct cw_action_in as, *af, *afm; */
|
||||
|
||||
int offset = cw_get_hdr_msg_offset(rawmsg);
|
||||
|
||||
uint8_t *msg_ptr = rawmsg + offset;
|
||||
|
||||
int elems_len = cw_get_msg_elems_len(msg_ptr);
|
||||
|
||||
int payloadlen = len - offset;
|
||||
|
||||
|
||||
/* pre-check message */
|
||||
if (payloadlen - 8 != elems_len) {
|
||||
|
||||
if (conn->strict_hdr) {
|
||||
cw_dbg(DBG_MSG_ERR,
|
||||
"Discarding message from %s, msgelems len=%d, payload len=%d, (Strict CAPWAP) ",
|
||||
sock_addr2str(&conn->addr, sock_buf), elems_len,
|
||||
payloadlen - 8);
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (elems_len < payloadlen - 8) {
|
||||
cw_dbg(DBG_RFC,
|
||||
"Packet from from %s has %d bytes of extra data, ignoring.",
|
||||
sock_addr2str(&conn->addr, sock_buf),
|
||||
payloadlen - 8 - elems_len);
|
||||
elems_len = len - 8;
|
||||
}
|
||||