Lots done in move to typeless

This commit is contained in:
7u83 2022-08-14 12:26:34 +02:00
parent b158544f1a
commit 459e2e2aeb
52 changed files with 1128 additions and 883 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,&params,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(&params,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(&params,elems_ptr, elems_len);
}
cw_MsgCallbackFun cb_fun = cw_conn_get_msg_cb(conn,message->type);
if (cb_fun != NULL){
result_code = cb_fun(&params,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;
}

View File

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

View File

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