2022-08-18 08:50:34 +02:00
|
|
|
#include "cw.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "dbg.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cw_encode_elements(struct cw_ElemHandlerParams *params, mlist_t elements_list, uint8_t * dst)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
struct mlistelem * elem;
|
|
|
|
|
|
|
|
len =0;
|
2022-08-22 01:59:23 +02:00
|
|
|
params->len=len;
|
|
|
|
|
2022-08-18 08:50:34 +02:00
|
|
|
mlist_foreach(elem,elements_list){
|
|
|
|
int l;
|
|
|
|
struct cw_ElemData * data;
|
|
|
|
struct cw_ElemHandler * handler;
|
|
|
|
|
|
|
|
data = mlistelem_dataptr(elem);
|
|
|
|
handler = cw_msgset_get_elemhandler(params->msgset,data->proto,data->vendor,data->id);
|
|
|
|
params->elemdata = data;
|
|
|
|
|
|
|
|
if (handler==NULL){
|
2022-08-21 00:53:41 +02:00
|
|
|
cw_dbg(DBG_MSG_COMPOSE," Add Elem: %d %d %d %s", data->proto, data->vendor, data->id, handler->name);
|
2022-08-18 08:50:34 +02:00
|
|
|
cw_log(LOG_ERR,"Can't put message element %d %d %d, no handler defined.",
|
|
|
|
data->proto,data->vendor,data->id);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (handler->put == NULL){
|
|
|
|
if (data->mand){
|
2022-08-21 00:53:41 +02:00
|
|
|
cw_dbg(DBG_MSG_COMPOSE," Add Elem: %d %d %d %s", data->proto, data->vendor, data->id, handler->name);
|
2022-08-18 08:50:34 +02:00
|
|
|
cw_log(LOG_ERR,"Error: Can't add mandatory message element %d - %s, no put method defined",
|
|
|
|
handler->id, handler->name);
|
|
|
|
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!data->mand){
|
|
|
|
if (!cw_cfg_base_exists(params->cfg_list[0],handler->key)){
|
2022-08-21 00:53:41 +02:00
|
|
|
cw_dbg(DBG_MSG_COMPOSE," Add Elem: %d %d %d %s - (skip)",
|
2022-08-20 01:59:27 +02:00
|
|
|
data->proto, data->vendor, data->id, handler->name);
|
|
|
|
|
2022-08-18 08:50:34 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
l = handler->put(handler,params,dst+len);
|
2022-08-21 00:53:41 +02:00
|
|
|
cw_dbg(DBG_MSG_COMPOSE," Add Elem: %d %d %d %s - (%d bytes)",
|
2022-08-20 01:59:27 +02:00
|
|
|
data->proto, data->vendor, data->id, handler->name,l);
|
2022-08-18 08:50:34 +02:00
|
|
|
|
2022-08-20 01:59:27 +02:00
|
|
|
len += l;
|
2022-08-22 01:59:23 +02:00
|
|
|
params->len=len;
|
2022-08-18 08:50:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Put a message to a buffer
|
|
|
|
* This functions assumes, that a message header is
|
|
|
|
* alread initialized in buffer
|
|
|
|
* Message alements are taken fom actiondef in #conn->action
|
|
|
|
*/
|
|
|
|
int cw_compose_message(struct cw_Conn *conn, uint8_t * rawout)
|
|
|
|
{
|
|
|
|
char details[1024];
|
|
|
|
uint8_t *msgptr,*dst;
|
|
|
|
int type;
|
|
|
|
struct cw_MsgData * msg;
|
|
|
|
int len;
|
|
|
|
struct cw_ElemHandlerParams params;
|
|
|
|
|
|
|
|
/* rawout is already initialized, so we can get
|
|
|
|
* msg type from buffer */
|
|
|
|
msgptr = rawout + cw_get_hdr_msg_offset(rawout);
|
|
|
|
type = cw_get_msg_type(msgptr);
|
|
|
|
|
|
|
|
/* look for message data */
|
|
|
|
msg = cw_msgset_get_msgdata(conn->msgset,type);
|
|
|
|
if (msg == NULL){
|
|
|
|
cw_log(LOG_ERR,"Error: Can't create message of type %d (%s) - no definition found.",
|
|
|
|
type, cw_strmsg(type));
|
|
|
|
return CAPWAP_RESULT_MSG_UNRECOGNIZED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg->preprocess){
|
|
|
|
msg->preprocess(conn);
|
|
|
|
}
|
|
|
|
|
2022-08-21 00:53:41 +02:00
|
|
|
cw_dbg(DBG_MSG_COMPOSE,"Composing message of type %d (%s) ***",
|
2022-08-18 08:50:34 +02:00
|
|
|
msg->type, msg->name);
|
|
|
|
|
|
|
|
dst = msgptr+8;
|
|
|
|
len =0;
|
2022-08-19 22:23:55 +02:00
|
|
|
//cw_dbg(DBG_X,"setting with update CFG");
|
2022-08-18 08:50:34 +02:00
|
|
|
params.conn=conn;
|
2022-08-22 01:59:23 +02:00
|
|
|
params.rawmsg = rawout;
|
2022-08-25 21:02:02 +02:00
|
|
|
params.cfg_list=conn->cfg_list;
|
2022-08-18 08:50:34 +02:00
|
|
|
params.msgset=conn->msgset;
|
|
|
|
params.msgdata=msg;
|
|
|
|
params.debug_details=details;
|
|
|
|
*details=0;
|
|
|
|
len = cw_encode_elements(¶ms,msg->elements_list,dst);
|
|
|
|
|
|
|
|
/* mlist_foreach(elem,msg->elements_list){
|
|
|
|
struct cw_ElemData * data;
|
|
|
|
struct cw_ElemHandler * handler;
|
|
|
|
|
|
|
|
data = mlistelem_dataptr(elem);
|
|
|
|
handler = cw_msgset_get_elemhandler(conn->msgset,data->proto,data->vendor,data->id);
|
2022-08-21 00:53:41 +02:00
|
|
|
cw_dbg(DBG_MSG_COMPOSE," Add Elem: %d %d %d %s", data->proto, data->vendor, data->id, handler->name);
|
2022-08-18 08:50:34 +02:00
|
|
|
if (handler==NULL){
|
|
|
|
cw_log(LOG_ERR,"Can't put message element %d %d %d, no handler defined.",
|
|
|
|
data->proto,data->vendor,data->id);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (handler->put == NULL){
|
|
|
|
if (data->mand){
|
|
|
|
cw_log(LOG_ERR,"Error: Can't add mandatory message element %d - %s, no put method defined",
|
|
|
|
handler->id, handler->name);
|
|
|
|
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
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);
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* if(l>0)
|
|
|
|
cw_dbg_elem(DBG_ELEM_OUT,conn,type,handler,dst+len,l);
|
|
|
|
* if (strlen(details)){
|
|
|
|
cw_dbg(DBG_ELEM_DETAIL," %s",params.debug_details);
|
|
|
|
}
|
|
|
|
*/ //len += l;
|
|
|
|
// }
|
|
|
|
|
|
|
|
cw_set_msg_elems_len(msgptr, len);
|
2022-08-21 00:53:41 +02:00
|
|
|
//cw_dbg(DBG_MSG_COMPOSE,"*** Done assenmbling message of type %d (%s) ***",
|
|
|
|
// msg->type, msg->name);
|
2022-08-18 08:50:34 +02:00
|
|
|
if (type & 1) {
|
|
|
|
/* It's a request, so we have to set seqnum */
|
|
|
|
int s = conn_get_next_seqnum(conn);
|
|
|
|
cw_set_msg_seqnum(msgptr,s);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
2022-08-20 21:00:46 +02:00
|
|
|
// printf ("----------------------------------- redecode -----------------------------\n");
|
|
|
|
/* uint8_t *elems_ptr;
|
2022-08-18 08:50:34 +02:00
|
|
|
|
|
|
|
int offset = cw_get_hdr_msg_offset(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);
|
|
|
|
cw_Cfg_t * cfg = cw_cfg_create();
|
|
|
|
|
|
|
|
struct cw_ElemHandlerParams params;
|
|
|
|
memset(¶ms,0,sizeof(struct cw_ElemHandlerParams));
|
|
|
|
|
|
|
|
params.cfg=cfg;
|
|
|
|
params.msgset=conn->msgset;
|
|
|
|
params.msgdata=msg;
|
|
|
|
params.mand_found = mavl_create_conststr();
|
2022-08-20 21:00:46 +02:00
|
|
|
params.dbg_level = DBG_ELEM_OUT;
|
2022-08-18 08:50:34 +02:00
|
|
|
|
|
|
|
cw_decode_elements( ¶ms, elems_ptr,elems_len);
|
|
|
|
cw_cfg_destroy(cfg);
|
|
|
|
if (params.mand_found){
|
|
|
|
cw_check_missing_mand(msg, params.mand_found,conn->msgset->handlers_by_key);
|
|
|
|
mavl_destroy(params.mand_found);
|
|
|
|
}
|
2022-08-20 21:00:46 +02:00
|
|
|
*/
|
|
|
|
// printf ("----------------------------------- end redecode -----------------------------\n");
|
2022-08-18 08:50:34 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return CAPWAP_RESULT_SUCCESS;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cw_decode_element(struct cw_ElemHandlerParams *params, int proto,
|
|
|
|
int vendor, int elem_id, uint8_t * data, int len)
|
|
|
|
{
|
|
|
|
|
|
|
|
struct cw_ElemHandler *handler;
|
|
|
|
struct cw_ElemData *elem_data, elem_data_search;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
//params->elem = NULL;
|
|
|
|
|
|
|
|
/* try to retrieve a handler for this message element */
|
|
|
|
handler =
|
|
|
|
cw_msgset_get_elemhandler(params->msgset, proto, vendor,
|
|
|
|
elem_id);
|
|
|
|
if (!handler) {
|
|
|
|
|
|
|
|
cw_dbg(DBG_ELEM_ERR,
|
|
|
|
"Unrecognized message element: %d, ignoring", elem_id);
|
|
|
|
return CAPWAP_RESULT_UNRECOGNIZED_MESSAGE_ELEMENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check if this message element in the current message allowed */
|
|
|
|
elem_data_search.id = elem_id;
|
|
|
|
elem_data_search.proto = proto;
|
|
|
|
elem_data_search.vendor = vendor;
|
2022-08-22 01:59:23 +02:00
|
|
|
if (params->msgdata)
|
|
|
|
elem_data = mavl_get(params->msgdata->elements_tree, &elem_data_search);
|
|
|
|
else
|
|
|
|
elem_data = NULL;
|
2022-08-18 08:50:34 +02:00
|
|
|
if (!elem_data) {
|
|
|
|
cw_dbg(DBG_ELEM_ERR, "Element %d - %s, not allowed here",
|
|
|
|
elem_id, handler->name);
|
|
|
|
return CAPWAP_RESULT_UNRECOGNIZED_MESSAGE_ELEMENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check the length of the message */
|
|
|
|
if (len < handler->min_len) {
|
|
|
|
cw_dbg(DBG_ELEM_ERR,
|
|
|
|
"%d (%s) message element too short, len=%d, min len=%d",
|
|
|
|
handler->id, handler->name, len, handler->min_len);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (elem_data->mand && params->mand_found) {
|
|
|
|
mavl_add_str(params->mand_found, handler->key);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (len > handler->max_len && handler->max_len) {
|
|
|
|
cw_dbg(DBG_ELEM_ERR,
|
|
|
|
"%d (%s) message element too big, len=%d, max len=%d",
|
|
|
|
handler->id, handler->name, len, handler->max_len);
|
|
|
|
/* TODO XXX truncate the element instead of return */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-08-22 01:59:23 +02:00
|
|
|
if (!handler->flags || cw_dbg_is_level(DBG_ELEM_VNDR))
|
2022-08-20 21:00:46 +02:00
|
|
|
cw_dbg_elem(params->dbg_level, NULL, params->msgdata->type, handler,
|
|
|
|
data, len);
|
2022-08-18 08:50:34 +02:00
|
|
|
|
|
|
|
if (handler->get == NULL) {
|
|
|
|
cw_log(LOG_ERR, "No get method defined for %d %s", handler->id,
|
|
|
|
handler->name);
|
|
|
|
return CAPWAP_RESULT_UNRECOGNIZED_MESSAGE_ELEMENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = handler->get(handler, params, data, len);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int cw_decode_elements(struct cw_ElemHandlerParams * params, uint8_t * elems_ptr, int elems_len)
|
|
|
|
{
|
|
|
|
uint8_t *elem;
|
|
|
|
// mavl_t mand_found;
|
|
|
|
// mlist_t unrecognized;
|
|
|
|
|
|
|
|
//mand_found = mavl_create_conststr();
|
|
|
|
//unrecognized = mlist_create(NULL,NULL,sizeof(uint8_t*));
|
|
|
|
cw_foreach_elem(elem, elems_ptr, elems_len) {
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
int elem_len, elem_id, max_len;
|
|
|
|
uint8_t * elem_data;
|
|
|
|
|
|
|
|
|
|
|
|
elem_len = cw_get_elem_len(elem);
|
|
|
|
elem_data=cw_get_elem_data(elem);
|
|
|
|
elem_id = cw_get_elem_id(elem);
|
|
|
|
|
|
|
|
max_len=elems_len-(elem_data-elems_ptr);
|
|
|
|
if (elem_len > max_len){
|
|
|
|
cw_dbg(DBG_RFC,
|
|
|
|
"Messag element claims size of %d bytes, but only %d bytes are left in the payload, truncating.",
|
|
|
|
elem_len,max_len-4);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
params->from=NULL; /*from;*/
|
|
|
|
// params->mand_found=mand_found;
|
|
|
|
|
|
|
|
rc = cw_decode_element(params,0,0,elem_id,elem_data,elem_len);
|
|
|
|
|
|
|
|
|
|
|
|
if (cw_result_is_ok(rc))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (rc == CAPWAP_RESULT_UNRECOGNIZED_MESSAGE_ELEMENT){
|
|
|
|
if (params->unrecognized)
|
|
|
|
mlist_append(params->unrecognized,&elem);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc < 0 ){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|