From af03e1c601cd3b1af45038db3c151d272a7265a4 Mon Sep 17 00:00:00 2001 From: "7u83@mail.ru" <7u83@mail.ru@noemail.net> Date: Mon, 5 Mar 2018 19:39:15 +0000 Subject: [PATCH] implementation of mavl kv (not working) FossilOrigin-Name: a20911b2dd992b0d382428c232b804b76e625985e574722931aa2fb163bedeaa --- libcw.project | 3 + src/ac/ac_main.c | 60 +++- src/ac/wtpman.c | 2 + src/cw/Doxyfile | 9 +- src/cw/capwap_items.h | 3 +- src/cw/conn.h | 4 + src/cw/conn_process_packet.c | 78 +++-- src/cw/cw_format_pkt_hdr.c | 107 +++++++ src/cw/cw_read_wtp_descriptor_versions.c | 3 +- src/cw/cw_type_byte.c | 37 +-- src/cw/cw_type_dword.c | 3 +- src/cw/cw_type_word.c | 2 + src/cw/cw_types.h | 36 ++- src/cw/dbg.c | 346 ++++++----------------- src/cw/dbg.h | 11 +- src/cw/format.h | 5 +- src/cw/lwapp.h | 14 +- src/cw/mavl.h | 20 +- src/cw/mavl_add.c | 18 +- src/cw/mavl_add_kv_byte.c | 9 + src/cw/mavl_cmp_kv.c | 5 + src/cw/mdata.h | 11 - src/cw/message_set.c | 48 +++- src/cw/message_set.h | 2 + src/mod/capwap/capwap_actions_ac.c | 2 +- 25 files changed, 495 insertions(+), 343 deletions(-) create mode 100644 src/cw/cw_format_pkt_hdr.c create mode 100644 src/cw/mavl_add_kv_byte.c create mode 100644 src/cw/mavl_cmp_kv.c diff --git a/libcw.project b/libcw.project index 41fae974..da3335b5 100644 --- a/libcw.project +++ b/libcw.project @@ -324,6 +324,9 @@ + + + diff --git a/src/ac/ac_main.c b/src/ac/ac_main.c index 2909c5a2..9b9115f0 100644 --- a/src/ac/ac_main.c +++ b/src/ac/ac_main.c @@ -94,10 +94,52 @@ extern struct cw_Mod * cw_get_mod_ac(const char *name); extern void test_sets(); #include "cw/file.h" +#include "cw/cw_types.h" +void cw_type_delete(mavldata_t *data){ + struct cw_Type * type = data->kv.priv; + printf("Delete elem of type: %s\n", type->name); + if (type->del) + type->del(data); + +} int main(int argc, char *argv[]) { + mavl_t kv; + mavliter_t kviter; + uint8_t bytes[] = { 99,4,5,7 }; + + + kv = mavl_create(mavl_cmp_kv,cw_type_delete); + + mavldata_t data, *result; + + data.kv.key="wtp_board_data"; + result = cw_type_byte.get(&data,bytes,1); + mavl_add(kv,result); + + data.kv.key="wtp_next_data"; + result = cw_type_byte.get(&data,bytes+1,1); + mavl_add(kv,result); + + + mavliter_init(&kviter,kv); + mavliter_foreach(&kviter){ + char value[500]; + mavldata_t * data; + data = mavliter_get(&kviter); + struct cw_Type * type = data->kv.priv; + type->to_str(data,value,0); + + printf("Got %s (%s): %s\n",data->kv.key,type->name, value); + } + + mavl_destroy(kv); + exit(0); + + + /* cw_log_init(); cw_log(LOG_ERROR,"Hello Debug World222"); exit(0); @@ -115,10 +157,24 @@ int main(int argc, char *argv[]) /* char data[100]; mavl_t im; - mavldata_t val,itt; + mavldata_t * val, * val2,itt, itt2, * result, search ; mavliter_t myit; im = mavl_create(mavl_cmp_dword,NULL); + itt.dword = 7; + itt2.dword = 7; + + + val = mavl_add(im,&itt); + val2 = mavl_add(im,&itt2); + + search.dword = 7; + result = mavl_get(im,&search); + + printf("Result: (%p, %p) (%p, %p) (%p, %p)\n",val, &itt, val2, &itt2, result, &search); + + exit(0); + for (itt.dword=100; itt.dword>0; itt.dword--){ printf("Copunting: %d\n",itt.dword); @@ -133,12 +189,12 @@ int main(int argc, char *argv[]) } mavl_destroy(im); + */ - int rc = 0; /* parse arguments */ diff --git a/src/ac/wtpman.c b/src/ac/wtpman.c index 36691da0..db968e39 100644 --- a/src/ac/wtpman.c +++ b/src/ac/wtpman.c @@ -96,6 +96,8 @@ static void wtpman_run_discovery(void *arg) wtpman->conn->outgoing = mbag_create(); wtpman->conn->incomming = mbag_create(); + + wtpman->conn->remote_cfg = mavl_create(mavl_cmp_kv,NULL); while (!cw_timer_timeout(timer) && wtpman->conn->capwap_state == CAPWAP_STATE_DISCOVERY) { diff --git a/src/cw/Doxyfile b/src/cw/Doxyfile index 4c5030de..53399d2e 100644 --- a/src/cw/Doxyfile +++ b/src/cw/Doxyfile @@ -220,7 +220,8 @@ TAB_SIZE = 8 # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. -ALIASES = +#ALIASES = +ALIASES = endcomment="\htmlonly*/\endhtmlonly\latexonly$\ast$/\endlatexonly" # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" @@ -811,14 +812,14 @@ EXCLUDE_SYMBOLS = # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = +EXAMPLE_PATH = ./examples # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. -EXAMPLE_PATTERNS = +EXAMPLE_PATTERNS = *.txt # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands @@ -848,7 +849,7 @@ IMAGE_PATH = # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. -INPUT_FILTER = +INPUT_FILTER = ./doxyfilter # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the diff --git a/src/cw/capwap_items.h b/src/cw/capwap_items.h index a8455a3f..7633b756 100644 --- a/src/cw/capwap_items.h +++ b/src/cw/capwap_items.h @@ -130,8 +130,9 @@ extern const char CW_ITEM_AC_TIMESTAMP[]; extern const char CW_ITEM_STATISTICS_TIMER[]; extern const char CW_ITEM_WTP_REBOOT_STATISTICS[]; extern const char CW_ITEM_IMAGE_IDENTIFIER[]; +/* //extern const char CW_ITEM_AC_HASH_VALUE[]; - +*/ extern const char CW_ITEM_AC_NAME_WITH_PRIORITY[]; extern const char CW_ITEM_MAXIMUM_MESSAGE_LENGTH[]; extern const char CW_ITEM_CAPWAP_TRANSPORT_PROTOCOL[]; diff --git a/src/cw/conn.h b/src/cw/conn.h index 48864af9..9c803c1e 100644 --- a/src/cw/conn.h +++ b/src/cw/conn.h @@ -70,6 +70,10 @@ struct conn { int recv_timeout; + + + mavl_t remote_cfg; + mbag_t outgoing; mbag_t incomming; diff --git a/src/cw/conn_process_packet.c b/src/cw/conn_process_packet.c index 820b6a53..eff7ac62 100644 --- a/src/cw/conn_process_packet.c +++ b/src/cw/conn_process_packet.c @@ -15,8 +15,6 @@ along with Foobar. If not, see . */ - - #include #include #include @@ -182,8 +180,9 @@ static struct cw_MsgSet *load_msg_set(struct conn *conn, uint8_t * rawmsg, int l int elems_len, struct sockaddr *from) { char sock_buf[SOCK_ADDR_BUFSIZE]; + struct cw_Mod *cmod, *bmod; - struct cw_Mod *cmod = + cmod = cw_mod_detect(conn, rawmsg, len, elems_len, from, CW_MOD_MODE_CAPWAP); if (cmod == MOD_NULL) { cw_dbg(DBG_MSG_ERR, @@ -192,17 +191,17 @@ static struct cw_MsgSet *load_msg_set(struct conn *conn, uint8_t * rawmsg, int l return NULL; } - struct cw_Mod *bmod = + bmod = cw_mod_detect(conn, rawmsg, len, elems_len, from, MOD_MODE_BINDINGS); cw_dbg(DBG_INFO, "Mods deteced: %s,%s", cmod->name, bmod->name); +/* // struct cw_actiondef *ad = mod_cache_add(conn,cmod, bmod); +*/ + return cw_mod_get_msg_set(conn,cmod,bmod); - struct cw_MsgSet * set = cw_mod_get_msg_set(conn,cmod,bmod); - - return set; } int cw_in_check_generic(struct conn *conn, struct cw_action_in *a, uint8_t * data, @@ -220,7 +219,8 @@ int cw_in_check_generic(struct conn *conn, struct cw_action_in *a, uint8_t * dat static int process_elements(struct conn *conn, uint8_t * rawmsg, int len, struct sockaddr *from) { - char sock_buf[SOCK_ADDR_BUFSIZE]; + 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); @@ -266,7 +266,9 @@ static int process_elements(struct conn *conn, uint8_t * rawmsg, int len, struct cw_MsgSet *set = load_msg_set(conn, rawmsg, len, elems_len, from); if (!set) { +/* //cw_log(LOG_ERR, "Error"); +*/ errno = EAGAIN; return -1; } @@ -337,10 +339,11 @@ static int process_elements(struct conn *conn, uint8_t * rawmsg, int len, } /* Execute start processor for message */ +/* // if (afm->start) { // afm->start(conn, afm, rawmsg, len, from); // } - +*/ uint8_t *elems_ptr = cw_get_msg_elems_ptr(msg_ptr); @@ -354,36 +357,71 @@ static int process_elements(struct conn *conn, uint8_t * rawmsg, int len, /* 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); + struct cw_ElemHandler *handler; + struct cw_ElemData * elem_data, elem_data_search; + int elem_len, elem_id; + + elem_id = cw_get_elem_id(elem); + + handler = cw_msgset_get_elemhandler(conn->msgset,0, 0, elem_id); + if (!handler) { + cw_dbg(DBG_ELEM_ERR, "Unknown message element: %d, ignoring", + elem_id); + continue; + } + + elem_data_search.id=elem_id; + elem_data_search.proto=0; + elem_data_search.vendor=0; + + elem_data = mavl_find_ptr(message->elements_tree,&elem_data_search); + + if (!elem_data){ + cw_dbg(DBG_ELEM_ERR, "Element %d - %s, not allowed here", + elem_id, handler->name); + continue; + } + + + elem_len = cw_get_elem_len(elem); + +printf ("Would start elem processing now %d - %s\n",handler->id, handler->name); +continue; +exit(0); + + + as.elem_id = cw_get_elem_id(elem); + /* int elem_len = cw_get_elem_len(elem);*/ + +/* //cw_elem_handler_t search_eh; //memset(&search_eh,0,sizeof(search_eh)); // struct cw_ElemDef search_elem; // search_elem.handler=&search_eh; // search_eh.id = cw_get_elem_id(elem); - +*/ struct cw_ElemDef * elem; - // elem = mavl_find(message->elements_tree,&search_elem); + + -//printf("ElemCHeck %d\n",search_eh.id); -//if (elem){ -//printf("Elem %d found! %s\n", elem->handler->id , elem->handler->name); -//} +/* // TODO XXX // af = cw_actionlist_in_get(conn->actions->in, &as); + */ af = 0; if (!af) { unrecognized++; - // TOOO XXXX + + /* cw_dbg(DBG_ELEM_ERR, "Element %d (%s) not allowed in msg of type %d (%s), ignoring.", - as.elem_id, cw_strelemp(conn->actions, as.elem_id), +// TODO XXXX as.elem_id, cw_strelemp(conn->actions, as.elem_id), as.msg_id, cw_strmsg(as.msg_id)); */ continue; @@ -411,8 +449,10 @@ static int process_elements(struct conn *conn, uint8_t * rawmsg, int len, } if(conn->elem_end){ +/* // TODO XXXX // afrc = conn->elem_end(conn,af,afrc,cw_get_elem_data(elem), elem_len,from); +*/ } } diff --git a/src/cw/cw_format_pkt_hdr.c b/src/cw/cw_format_pkt_hdr.c new file mode 100644 index 00000000..b861b8aa --- /dev/null +++ b/src/cw/cw_format_pkt_hdr.c @@ -0,0 +1,107 @@ +#include "format.h" +#include "sock.h" +#include "conn.h" +#include "cw.h" + +/** + * @brief Format a packet header for debugging purposes + * @param dst Destination buffer + * @param incomming True if the packet is an incomming packet, otherweise 0 + * @param packet packet data + * @param len length of packet data + * @param from Address from where the packet was received + * @return Number of bytes written + */ +int cw_format_pkt_hdr(char *dst, int incomming, uint8_t * packet, int len, + struct sockaddr *from) +{ + char sock_buf[SOCK_ADDR_BUFSIZE]; + int preamble; + char *s; + int hlen, rid, wbid; + int frag_id,frag_offs; + + s = dst; + + if (incomming){ + if (cw_get_hdr_flag_f(packet)) { + s += sprintf(s, "Fragment from %s", + sock_addr2str_p(from,sock_buf)); + } else { + s += sprintf(s, "From %s", sock_addr2str_p(from,sock_buf)); + } + } + else{ + if (cw_get_hdr_flag_f(packet)) { + s += sprintf(s, "Fragment to %s", sock_addr2str(from,sock_buf)); + } else { + s += sprintf(s, "To %s", sock_addr2str(from,sock_buf)); + } + } + s += sprintf(s, " l=%d: ", len); + + preamble = cw_get_hdr_preamble(packet); + if (preamble == 01) { + s += sprintf(s, " (encrypted)"); + return s - dst; + } + + if (len < 4) + goto abort; + +/* + if (cw_get_hdr_flag_f(packet)){ + s+=sprintf(s," (fragmented)"); + } +*/ + hlen = cw_get_hdr_hlen(packet); + rid = cw_get_hdr_rid(packet); + wbid = cw_get_hdr_wbid(packet); + s += sprintf(s, " H:%d R:%02d W:%02d", hlen, rid, wbid); + + + s += sprintf(s, " Flgs:"); + s += format_hdr_flags(s, packet); + + if (len < 8) + goto abort; + frag_id = cw_get_hdr_fragid(packet); + frag_offs = cw_get_hdr_fragoffset(packet); + s += sprintf(s, " Frag/Offs:%d/%d", frag_id, frag_offs); + + + if (cw_get_hdr_flag_m(packet)) { + /* rmac is present, print the rmac */ + int rmac_len = cw_get_hdr_rmac_len(packet); + int plen = rmac_len; + if (rmac_len + 8 > len) + plen = len - 8; + if (rmac_len > 10) + plen = 10; + + s += sprintf(s, " R-MAC:"); + s += format_mac(s, cw_get_hdr_rmac_data(packet), plen); + if (rmac_len > 10) { + s += sprintf(s, " ... (len=%d)", rmac_len); + } + } + + if (cw_get_hdr_flag_w(packet)) { + /* print wireless specific info */ + int ws_len = cw_get_hdr_ws_len(packet); + int plen = ws_len > 20 ? 20 : ws_len; + s += sprintf(s, " WS:"); + s += format_hexu(s, cw_get_hdr_ws_data(packet), plen); + if (ws_len > 20) { + s += sprintf(s, " ... (len=%d)", ws_len); + } + } + return s - dst; + + + + abort: + s += sprintf(s, " Incomplete..."); + return s - dst; + +} diff --git a/src/cw/cw_read_wtp_descriptor_versions.c b/src/cw/cw_read_wtp_descriptor_versions.c index 1b9c889b..b27a4273 100644 --- a/src/cw/cw_read_wtp_descriptor_versions.c +++ b/src/cw/cw_read_wtp_descriptor_versions.c @@ -33,7 +33,8 @@ int cw_read_wtp_descriptor_versions(mbag_t mbag, uint8_t * data, int len) char *dmp; char *dmpmem = NULL; if (cw_dbg_is_level(DBG_SUBELEM_DMP)) { - dmpmem = cw_dbg_mkdmp(data + i, sublen); +/* TODO XXX */ + dmpmem = NULL; /*cw_dbg_mkdmp(data + i, sublen);*/ dmp = dmpmem; } else dmp = ""; diff --git a/src/cw/cw_type_byte.c b/src/cw/cw_type_byte.c index 363f1b25..7bf84700 100644 --- a/src/cw/cw_type_byte.c +++ b/src/cw/cw_type_byte.c @@ -21,7 +21,7 @@ #include "cw.h" #include "cw_types.h" - +/* static struct mdata_Elem *from_str(const char *src) { struct mdata_Elem *i = mdata_elem_new(&cw_type_byte); @@ -37,26 +37,31 @@ static int to_str(const struct mdata_Elem *e, char *dst) { return sprintf(dst, "%d", e->data.byte); } +*/ -static struct mdata_Elem *get(const uint8_t * src, int len) +static mavldata_t *get(mavldata_t * data, const uint8_t * src, int len) { - struct mdata_Elem *e = mdata_elem_new(&cw_type_byte); - if (!e) - return NULL; - e->data.byte = cw_get_byte(src); - return e; + data->kv.priv = &cw_type_byte; + data->kv.val.byte = cw_get_byte(src); + return data; } -static int put(struct mdata_Elem *e, uint8_t * dst) +static int put(mavldata_t *data, uint8_t * dst) { - return cw_put_byte(dst, e->data.byte); + return cw_put_byte(dst, data->kv.val.byte); } -#define _I_NAME "Byte" -#define _I_PUT put -#define _I_GET get -#define _I_DEL NULL -#define _I_TO_STR to_str -#define _I_FROM_STR from_str +static int to_str(const mavldata_t *data, char *dst, int max_len) +{ + return sprintf(dst, "%d", data->kv.val.byte); +} + +const struct cw_Type cw_type_byte = { + "Byte", /* name */ + NULL, /* del */ + put, /* put */ + get, /* get */ + to_str /* to_str */ +}; + -const struct mdata_Type cw_type_byte = MDATA_TYPE_INIT(); diff --git a/src/cw/cw_type_dword.c b/src/cw/cw_type_dword.c index e01dd725..27df4313 100644 --- a/src/cw/cw_type_dword.c +++ b/src/cw/cw_type_dword.c @@ -20,7 +20,7 @@ #include "cw_types.h" #include "cw.h" - +/* static struct mdata_Elem * from_str(const char *src) { struct mdata_Elem * e = mdata_elem_new(&cw_type_dword); @@ -59,3 +59,4 @@ static int put(struct mdata_Elem * e, uint8_t *dst) #define _I_FROM_STR from_str const struct mdata_Type cw_type_dword = MDATA_TYPE_INIT(); +*/ \ No newline at end of file diff --git a/src/cw/cw_type_word.c b/src/cw/cw_type_word.c index dc63f2bd..11857fa0 100644 --- a/src/cw/cw_type_word.c +++ b/src/cw/cw_type_word.c @@ -21,6 +21,7 @@ #include "cw_types.h" #include "cw.h" +/* static struct mdata_Elem * from_str(const char *src) { struct mdata_Elem * e = mdata_elem_new(&cw_type_word); @@ -59,3 +60,4 @@ static int put(struct mdata_Elem * e, uint8_t *dst) #define _I_FROM_STR from_str const struct mdata_Type cw_type_word = MDATA_TYPE_INIT(); +*/ \ No newline at end of file diff --git a/src/cw/cw_types.h b/src/cw/cw_types.h index 8d26354b..dbddbac0 100644 --- a/src/cw/cw_types.h +++ b/src/cw/cw_types.h @@ -1,12 +1,44 @@ #ifndef __CW_TYPES_H #define __CW_TYPES_H -#include "mdata.h" +#include "mavl.h" -extern const struct mdata_Type cw_type_byte; +struct cw_Type{ + /** A human readable name for this type */ + const char *name; + + /** A pointer to a function to delete elements of this type */ + void (*del)(mavldata_t *data); + + /** A method to put this object to a buffer */ + int (*put)(mavldata_t * data, uint8_t*dst); + + /** The get emthod */ + mavldata_t * (*get)(mavldata_t *data, const uint8_t*src, int len); + + /** A pointer to a function to convert elements of this type to a string. + This function is mainly used to store elements to an SQL database + or to json strings */ + int (*to_str)(const mavldata_t * data, char *dst, int max_len); + + /** Cereate an item of this type from a string, which was previously + created by the #del function. */ +/* struct mdata_Elem * (*from_str)(const char *src);*/ + +/* + int (*def)(void *, void *); +*/ + + +}; + + +extern const struct cw_Type cw_type_byte; #define CW_TYPE_BYTE (&cw_type_byte) extern const struct mdata_Type cw_type_word; extern const struct mdata_Type cw_type_dword; + + #endif diff --git a/src/cw/dbg.c b/src/cw/dbg.c index 755d0339..a503def0 100644 --- a/src/cw/dbg.c +++ b/src/cw/dbg.c @@ -19,8 +19,6 @@ - - /** * @file Debugging Functions * @brief Various debug functions. @@ -31,7 +29,6 @@ #include "capwap.h" #include "dbg.h" #include "sock.h" - #include "log.h" #include "strlist.h" #include "format.h" @@ -147,9 +144,6 @@ static struct cw_strlist_elem prefix[] = { {CW_STR_STOP, ""} }; - - - static const char *get_dbg_color_on(int level) { if (!(cw_dbg_opt_display & DBG_DISP_COLORS)) @@ -191,17 +185,23 @@ static const char *get_dbg_color_ontext(int level) 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_MSG_ERR) || n == 0) // return; +*/ - if (!cw_dbg_is_level(level) || n == 0) - return; char buffer[2000]; - char *p = buffer; +/* char *p = buffer; */ int i; - char *delim = ""; +/* char *delim = "";*/ + + if (!cw_dbg_is_level(level) || n == 0) + return; + +/* // TODO XXXX +*/ for (i = 0; i < n; i++) { /* p += sprintf(p, "%s", delim); delim = ", "; @@ -211,207 +211,6 @@ void cw_dbg_missing_mand(int level, struct conn *conn, cw_action_in_t ** ml, int cw_dbg(level, "Missing mandatory elements: [%s]", buffer); } -/** - * Format a Packet Header - */ -int cw_format_pkt_hdr(char *dst, int level, struct conn *conn, uint8_t * packet, int len, - struct sockaddr *from) -{ - - char sock_buf[SOCK_ADDR_BUFSIZE]; - - char *s = dst; - switch (level) { - case DBG_PKT_IN: - if (cw_get_hdr_flag_f(packet)) { - s += sprintf(s, "Fragment from %s", - sock_addr2str_p(from,sock_buf)); - } else { - s += sprintf(s, "From %s", sock_addr2str_p(from,sock_buf)); - } - break; - case DBG_PKT_OUT: - if (cw_get_hdr_flag_f(packet)) { - s += sprintf(s, "Fragment to %s", sock_addr2str(from,sock_buf)); - } else { - s += sprintf(s, "To %s", sock_addr2str(from,sock_buf)); - } - break; - } - s += sprintf(s, " l=%d: ", len); - - int preamble = cw_get_hdr_preamble(packet); - if (preamble == 01) { - s += sprintf(s, " (encrypted)"); - return s - dst; - } - - if (len < 4) - goto abort; - -/* - if (cw_get_hdr_flag_f(packet)){ - s+=sprintf(s," (fragmented)"); - } -*/ - int hlen = cw_get_hdr_hlen(packet); - int rid = cw_get_hdr_rid(packet); - int wbid = cw_get_hdr_wbid(packet); - s += sprintf(s, " H:%d R:%02d W:%02d", hlen, rid, wbid); - - - s += sprintf(s, " Flgs:"); - s += format_hdr_flags(s, packet); - - if (len < 8) - goto abort; - int frag_id = cw_get_hdr_fragid(packet); - int frag_offs = cw_get_hdr_fragoffset(packet); - s += sprintf(s, " Frag/Offs:%d/%d", frag_id, frag_offs); - - - if (cw_get_hdr_flag_m(packet)) { - /* rmac is present, print the rmac */ - int rmac_len = cw_get_hdr_rmac_len(packet); - int plen = rmac_len; - if (rmac_len + 8 > len) - plen = len - 8; - if (rmac_len > 10) - plen = 10; - - s += sprintf(s, " R-MAC:"); - s += format_mac(s, cw_get_hdr_rmac_data(packet), plen); - if (rmac_len > 10) { - s += sprintf(s, " ... (len=%d)", rmac_len); - } - } - - if (cw_get_hdr_flag_w(packet)) { - /* print wireless specific info */ - int ws_len = cw_get_hdr_ws_len(packet); - int plen = ws_len > 20 ? 20 : ws_len; - s += sprintf(s, " WS:"); - s += format_hexu(s, cw_get_hdr_ws_data(packet), plen); - if (ws_len > 20) { - s += sprintf(s, " ... (len=%d)", ws_len); - } - } - - - - return s - dst; - - - - abort: - s += sprintf(s, " Incomplete..."); - return s - dst; - -} - -/** - * Create an ASCII hex dump of binary data - * - * @param data data to dump - * @param len number of bytes to dump (size of data) - * @return a character string with the created data ASCII dump (must be released with free) - */ -char *cw_dbg_mkdmp_c(const uint8_t * data, int len, int invlen) -{ - - int maxtlen = 2048; - int i; - int rowlen = CW_LOG_DUMP_ROW_LEN; - int rows = len / rowlen; - int tlen = 0; - - int md; - if (cw_dbg_opt_display & DBG_DISP_ASC_DMP) - md = 2; - else - md = 1; - - - - char *dst = malloc(2 * (md * (len * 3 + (rows * 2) + 8 + maxtlen))); - if (!dst) - return NULL; - - if (len % CW_LOG_DUMP_ROW_LEN) - rows++; - - - char *pdst = dst + tlen; - sprintf(pdst, "\n\t"); - pdst += 2; - - char asc_buffer[128]; - char *ascdst = asc_buffer; - -// if (invlen) { -// pdst+=sprintf(pdst,"\x1b[7m"); -// } - - for (i = 0; i < len; i++) { - char *sp = " "; - if (i == invlen - 1) - sp = "|"; -// if (i==invlen){ -// pdst+=sprintf(pdst,"\x1b[27m"); -// } - - pdst += sprintf(pdst, "%02X%s", data[i] & 0xff, sp); - if (cw_dbg_opt_display & DBG_DISP_ASC_DMP) { - int c = data[i] & 0xff; - if (c < 0x20 || c > 0x7f) - c = '.'; - *ascdst = c; - ascdst++; - } -// pdst += 3; - if ((i + 1) % rowlen == 0) { - int l; - if (cw_dbg_opt_display & DBG_DISP_ASC_DMP) { - *ascdst = 0; - l = sprintf(pdst, " | %s\n\t", asc_buffer); - ascdst = asc_buffer; - - } else { - l = sprintf(pdst, "\n\t"); - } - pdst += l; - } - - } - - if (cw_dbg_opt_display & DBG_DISP_ASC_DMP) { - *ascdst = 0; - if (strlen(asc_buffer)) - pdst += sprintf(pdst, " | %s", asc_buffer); - - } - - return dst; -} - - - - -char *cw_dbg_mkdmp(const uint8_t * data, int len) -{ - return cw_dbg_mkdmp_c(data, len, 0); -} - - - - - - - - - - - @@ -421,16 +220,27 @@ char *cw_dbg_mkdmp(const uint8_t * data, int len) void cw_dbg_pkt(int level, struct conn *conn, uint8_t * packet, int len, struct sockaddr *from) { + + int hlen; + char buf[1024]; + if (!cw_dbg_is_level(level)) return; - - char buf[1024]; - cw_format_pkt_hdr(buf, level, conn, packet, len, from); - - int hlen = cw_get_hdr_msg_offset(packet); + + if (level == DBG_PKT_IN) + cw_format_pkt_hdr(buf, 1, packet, len, from); + else + cw_format_pkt_hdr(buf, 0, packet, len, from); + + hlen = cw_get_hdr_msg_offset(packet); if (cw_dbg_is_level(DBG_PKT_DMP)) { + /* char *dmp = cw_dbg_mkdmp_c(packet, len, hlen); + */ + char * dmp; + dmp = cw_format_dump(packet,len,NULL); + cw_dbg(level, "%s%s", buf, dmp); free(dmp); } else @@ -440,6 +250,7 @@ void cw_dbg_pkt(int level, struct conn *conn, uint8_t * packet, int len, void cw_dbg_pkt_nc(int level, struct netconn *nc, uint8_t * packet, int len, struct sockaddr *from) { +/* if (!cw_dbg_is_level(level)) return; @@ -454,6 +265,7 @@ void cw_dbg_pkt_nc(int level, struct netconn *nc, uint8_t * packet, int len, free(dmp); } else cw_dbg(level, "%s", buf); +*/ } @@ -461,42 +273,50 @@ void cw_dbg_pkt_nc(int level, struct netconn *nc, uint8_t * packet, int len, -void cw_dbg_dmp_(int level, const uint8_t * data, int len, const char *format, ...) +void cw_dbg_dmp(int level, const uint8_t * data, int len, const char *format, ...) { + char *dmp; + if (!cw_dbg_is_level(level)) return; - - char *dmp = cw_dbg_mkdmp(data, len); + dmp = cw_format_dump(data, len, NULL); cw_dbg(level, "%s%s", format, dmp); free(dmp); - - } void cw_dbg_msg(int level, struct conn *conn, uint8_t * packet, int len, struct sockaddr *from) { - if (!cw_dbg_is_level(level)) - return; + char sock_buf[SOCK_ADDR_BUFSIZE]; char buf[1024]; - char *s = buf; - - - - uint8_t *msgptr = cw_get_hdr_msg_ptr(packet); -// int pplen = len - (msgptr-packet); - - int msg_id = cw_get_msg_id(msgptr); - + char *s; struct cw_MsgData search; - search.type = msg_id; struct cw_MsgData * message; + const char * msname; + uint8_t *msgptr; + int msg_id; + + if (!cw_dbg_is_level(level)) + return; + + s = buf; + + + msgptr = cw_get_hdr_msg_ptr(packet); +/* +// int pplen = len - (msgptr-packet); +*/ + msg_id = cw_get_msg_id(msgptr); + + + search.type = msg_id; + message = mavl_get_ptr(conn->msgset->messages,&search); - char * msname; + if (!message) msname="Unknown"; else @@ -510,14 +330,16 @@ void cw_dbg_msg(int level, struct conn *conn, uint8_t * packet, int len, s += sprintf(s, ", Seqnum: %d ElemLen: %d", cw_get_msg_seqnum(msgptr), cw_get_msg_elems_len(msgptr)); - +/* //abort: + */ cw_dbg(level, "%s", buf); } static int cw_format_vendor(char *dst, uint32_t vendor_id, int elem_id, const uint8_t * elem_data) { + uint32_t lw_elem_id; switch (vendor_id) { case CW_VENDOR_ID_CISCO: { @@ -528,7 +350,7 @@ static int cw_format_vendor(char *dst, uint32_t vendor_id, int elem_id, /* dive into LWAPP vendor specific decoding */ - uint32_t lw_elem_id = lw_get_word(elem_data + 4 + 6); + lw_elem_id = lw_get_word(elem_data + 4 + 6); return sprintf(dst, "%d/LWAPP Vendor: %d - %s", elem_id, lw_elem_id, lw_cisco_id_to_str(lw_elem_id)); @@ -560,15 +382,21 @@ static int cw_format_vendor(char *dst, uint32_t vendor_id, int elem_id, void cw_dbg_elem_colored(int level, struct conn *conn, int msg, int msgelem, const uint8_t * msgbuf, int len) { - if (!cw_dbg_is_level(level)) - return; + const char *elemname; char vendorname[256]; char vendor_details[265]; - *vendor_details = 0; -/// TODO XXXX + if (!cw_dbg_is_level(level)) + return; + + *vendor_details = 0; + + +/* +/// TODO XXXX +*/ if (msgelem == CAPWAP_ELEM_VENDOR_SPECIFIC_PAYLOAD) { uint32_t vendor_id = ntohl(*((uint32_t *) msgbuf)); int type = ntohs(*((uint16_t *) (msgbuf + 4))); @@ -580,7 +408,9 @@ void cw_dbg_elem_colored(int level, struct conn *conn, int msg, int msgelem, elemname = vendorname; } else { +/* // elemname = cw_strelemp(conn->actions, msgelem); +*/ elemname=0; } @@ -588,7 +418,11 @@ void cw_dbg_elem_colored(int level, struct conn *conn, int msg, int msgelem, if (!cw_dbg_is_level(DBG_ELEM_DMP)) { cw_dbg(DBG_ELEM, "%d (%s), len=%d", msgelem, elemname, len); } else { + /* char *dmp = cw_dbg_mkdmp(msgbuf, len); + */ + char *dmp; + dmp = cw_format_dump(msgbuf,len,NULL); cw_dbg(DBG_ELEM, "%d (%s), len=%d%s%s", msgelem, elemname, len, get_dbg_color_ontext(DBG_ELEM_DMP), dmp); @@ -598,14 +432,15 @@ void cw_dbg_elem_colored(int level, struct conn *conn, int msg, int msgelem, } -void cw_dbg_colored(int level, const char *format, ...) +void cw_dbg(int level, const char *format, ...) { + char fbuf[1024]; + va_list args; + if (!(cw_dbg_is_level(level))) return; - char fbuf[1024]; - sprintf(fbuf, "DBG:%s%s %s%s%s", get_dbg_color_on(level), get_dbg_prefix(level), @@ -613,7 +448,6 @@ void cw_dbg_colored(int level, const char *format, ...) ); - va_list args; va_start(args, format); /* cw_log_vcb(level, fbuf, args);*/ cw_log_console_writer.write(LOG_DEBUG,fbuf,args,&cw_log_console_writer); @@ -621,8 +455,9 @@ void cw_dbg_colored(int level, const char *format, ...) } +/* //int cw_is_utf8(unsigned char *str, size_t len); - +*/ int cw_format_item(char *dst, mbag_item_t * item) { @@ -639,17 +474,20 @@ int cw_format_item(char *dst, mbag_item_t * item) static int cw_format_version(char *s, bstrv_t ver, char *def) { + int dot; + uint8_t *version; + int len,rs,i; + uint32_t vendor; + if (!ver) return sprintf(s, "%s", def); - uint8_t *version = bstrv_data(ver); - int len = bstrv_len(ver); + version = bstrv_data(ver); + len = bstrv_len(ver); - - - int rs = 0; - int i; + rs = 0; + if (format_is_utf8(version, len)) { @@ -662,7 +500,7 @@ static int cw_format_version(char *s, bstrv_t ver, char *def) rs += sprintf(s + rs, "%02X", version[i]); } - int dot = 0; + dot = 0; rs += sprintf(s + rs, " ("); for (i = 0; i < len && i < 20; i++) { @@ -674,7 +512,7 @@ static int cw_format_version(char *s, bstrv_t ver, char *def) rs += sprintf(s + rs, ")"); } - uint32_t vendor = bstrv_get_vendor_id(ver); + vendor = bstrv_get_vendor_id(ver); rs += sprintf(s + rs, ", Vendor Id: %d, %s", vendor, cw_strvendor(vendor)); return rs; } @@ -683,11 +521,11 @@ static int cw_format_version(char *s, bstrv_t ver, char *def) void cw_dbg_version_subelem(int level, const char *context, int subtype, bstrv_t vstr) { + char v[256]; if (!cw_dbg_is_level(level)) return; if (!vstr) return; - char v[256]; cw_format_version(v, vstr, ""); cw_dbg(level, "%s: SubType %d, %s", context, subtype, v); diff --git a/src/cw/dbg.h b/src/cw/dbg.h index 6b54bff0..6f1b03e0 100644 --- a/src/cw/dbg.h +++ b/src/cw/dbg.h @@ -46,6 +46,9 @@ 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); +void cw_dbg_pkt(int level,struct conn *conn, uint8_t * packet, int len,struct sockaddr *from); +void cw_dbg(int level, const char *format, ...); +void cw_dbg_dmp(int level, const uint8_t * data, int len, const char *format, ...); /* #define DBGX(f,...) cw_dbg(DBG_X,f,__VA_ARGS__) //cw_dbg(DBG_X, f ,__VA_ARGS__) @@ -96,22 +99,24 @@ extern uint32_t cw_dbg_opt_display; extern uint32_t cw_dbg_opt_level; extern struct cw_strlist_elem cw_dbg_strings[]; - +/* #define cw_dbg cw_dbg_colored +*/ /* #define cw_dbg_dmp(type,...) cw_dbg_dmp_(type,__FILE__,__LINE__,__VA_ARGS__) */ +/* #define cw_dbg_dmp cw_dbg_dmp_ +*/ -void cw_dbg_colored(int level, const char *format, ...); void cw_dbg_dmp_(int level, const uint8_t * data, int len, const char *format, ...); extern void cw_dbg_elem_colored(int level, struct conn *conn, int msg, int msgelem, const uint8_t * msgbuf, int len); -void cw_dbg_pkt(int level,struct conn *conn, uint8_t * packet, int len,struct sockaddr *from); + void cw_dbg_pkt_nc(int level,struct netconn *nc, uint8_t * packet, int len,struct sockaddr *from); void cw_dbg_msg(int level,struct conn *conn, uint8_t * packet, int len,struct sockaddr *from); diff --git a/src/cw/format.h b/src/cw/format.h index 729908fc..4a3cb018 100644 --- a/src/cw/format.h +++ b/src/cw/format.h @@ -28,6 +28,8 @@ #include #include +#include "sock.h" + int format_hex_bytes(char *dst, const char *format, const char *delim, const uint8_t * src, int len); @@ -104,7 +106,8 @@ char *cw_format_dump(const uint8_t * data, int len, struct cw_FormatDumpSettings *settings); void cw_format_get_dump_defaults(struct cw_FormatDumpSettings * settings); - +int cw_format_pkt_hdr(char *dst, int incomming, uint8_t * packet, int len, + struct sockaddr *from); /**@}*/ diff --git a/src/cw/lwapp.h b/src/cw/lwapp.h index 53bd0e39..f1cacf10 100644 --- a/src/cw/lwapp.h +++ b/src/cw/lwapp.h @@ -85,10 +85,10 @@ - +/* //#define LWAPP_PACKET_PREAMBLE (CW_VERSION<<4) //#define LWAPP_DTLS_PACKET_PREAMBLE (CW_VERSION<<4|1) - +*/ #define LW_MSG_DISCOVERY_REQUEST 1 @@ -277,17 +277,23 @@ static inline int lw_put_elem_hdr(uint8_t *dst,uint8_t type,uint16_t len) extern int lw_put_cisco_path_mtu(uint8_t *dst, uint16_t max, uint16_t padding); #define lw_put_certificate(dst,cert,len) lw_put_data(dst,cert,len) -//extern int lw_put_ac_descriptor(uint8_t * dst, struct ac_info * acinfo); +/* +//extern int lw_put_ac_descriptor(uint8_t * dst, struct ac_info * acinfo); +*/ /* function proto types */ +/* //extern uint16_t lw_checksum(uint8_t *d,int len); //extern int lw_readelem_wtp_board_data(struct wtpinfo *wtpinfo, int type, uint8_t *msgelem, int len); +*/ + extern int lw_readelem_wtp_name(bstr_t * dst, int type, uint8_t * msgelem, int len); - +/* //extern int lw_put_80211_wtp_wlan_radio_configuration(uint8_t*dst,struct radioinfo *ri); +*/ extern const char * lw_vendor_id_to_str(uint32_t vendor_id); extern const char * lw_elem_id_to_str(int elem_id); diff --git a/src/cw/mavl.h b/src/cw/mavl.h index 08f34898..4f91a737 100644 --- a/src/cw/mavl.h +++ b/src/cw/mavl.h @@ -52,6 +52,18 @@ /** * @} */ + +struct mavl_KeyVal{ + const char *key; + const void *priv; + union{ + void * ptr; + uint32_t dword; + uint16_t word; + uint8_t byte; + char * str; + }val; +}; union mavldata { void *ptr; @@ -59,6 +71,7 @@ union mavldata { uint16_t word; uint8_t byte; char *str; + struct mavl_KeyVal kv; }; typedef union mavldata mavldata_t; @@ -66,8 +79,8 @@ typedef union mavldata mavldata_t; * Defines the structure of an AVL Node. */ struct mavlnode { - /** Pointer to data, thant belongs to the node */ - /* void *data; */ + /** Pointer to data, that belongs to the node */ + union mavldata data; /** Pointer to left son*/ struct mavlnode *left; @@ -114,6 +127,9 @@ struct mavlnode *mavl_get_node(struct mavl *t, union mavldata *data); void * mavl_get_ptr(mavl_t tree, void * search); void *mavl_add_ptr(mavl_t tree, void *ptr); +int mavl_cmp_kv(const union mavldata *e1, const union mavldata *e2); +union mavldata *mavl_add_kv_byte(mavl_t tree, const char *key, uint8_t val); + void mavl_merge(mavl_t m, mavl_t t); diff --git a/src/cw/mavl_add.c b/src/cw/mavl_add.c index e5e2bb21..a09e93e0 100644 --- a/src/cw/mavl_add.c +++ b/src/cw/mavl_add.c @@ -125,10 +125,6 @@ static int mavl_add0(struct mavl *t, struct mavlnode **parent, union mavldata * n->right->bal = 0; } - - - - (*parent)->bal = 0; n->right->left = (*parent)->right; (*parent)->right = n->right; @@ -162,10 +158,18 @@ static int mavl_add0(struct mavl *t, struct mavlnode **parent, union mavldata * /** * Add an element to an AVL tree - * @t mavl - * @data pointer to element - * @return added alement or NULL if error. + * + * @param t mavl + * @param data pointer to element + * + * @return A pointer to the element in the tree. If teh returned pointer + * equals to the pointer given in the data argument, the element has already + * been in the tree. If the function returns NULL, there was en error, e.g. + * no memory left. Consult therefore errno. + * + * @example mavl_add_example.c */ + union mavldata *mavl_add(struct mavl *t, union mavldata *data) { union mavldata * d; diff --git a/src/cw/mavl_add_kv_byte.c b/src/cw/mavl_add_kv_byte.c new file mode 100644 index 00000000..85a0fba4 --- /dev/null +++ b/src/cw/mavl_add_kv_byte.c @@ -0,0 +1,9 @@ +#include "mavl.h" + +union mavldata *mavl_add_kv_byte(mavl_t tree, const char *key, uint8_t val) +{ + mavldata_t data; + data.kv.key = key; + data.kv.val.byte = val; + return mavl_add(tree, &data); +} diff --git a/src/cw/mavl_cmp_kv.c b/src/cw/mavl_cmp_kv.c new file mode 100644 index 00000000..d370b13b --- /dev/null +++ b/src/cw/mavl_cmp_kv.c @@ -0,0 +1,5 @@ +#include "mavl.h" + +int mavl_cmp_kv(const union mavldata *e1, const union mavldata *e2){ + return strcmp(e1->kv.key, e2->kv.key); +} diff --git a/src/cw/mdata.h b/src/cw/mdata.h index 04efb873..dad3baf8 100644 --- a/src/cw/mdata.h +++ b/src/cw/mdata.h @@ -50,17 +50,6 @@ struct mdata_Type{ }; -#define MDATA_TYPE_INIT()\ - {\ - _I_NAME,\ - _I_DEL,\ - _I_PUT,\ - _I_GET,\ - _I_TO_STR,\ - _I_FROM_STR \ - } - - struct mdata_Elem *mdata_elem_new( const struct mdata_Type * type ); diff --git a/src/cw/message_set.c b/src/cw/message_set.c index 61a7ffa5..2223c0d0 100644 --- a/src/cw/message_set.c +++ b/src/cw/message_set.c @@ -3,6 +3,7 @@ #include "mavl.h" #include "debug.h" +#include "dbg.h" #include "log.h" #include "message_set.h" @@ -155,6 +156,7 @@ static int update_msgdata(struct cw_MsgSet * set, struct cw_MsgData * msgdata, struct cw_MsgDef * msgdef) { struct cw_ElemDef * elemdef; + mavldata_t mavldata, *result; /* iterate through all defined elements */ for(elemdef = msgdef->elements; elemdef->id; elemdef++){ @@ -164,7 +166,7 @@ static int update_msgdata(struct cw_MsgSet * set, struct cw_MsgData * msgdata, elemdef->proto, elemdef->vendor, elemdef->id); - + /* check if a handler for our element already exists */ if (!handler){ cw_log(LOG_ERR, "No handler for message element: %d %d %d", elemdef->proto, @@ -172,14 +174,33 @@ static int update_msgdata(struct cw_MsgSet * set, struct cw_MsgData * msgdata, elemdef->id); continue; } - - DBG_START(NULL,DBG_INFO) - "Have an element %d %d %d, %s", + + mavldata.ptr = malloc(sizeof(struct cw_ElemData)); + if (!mavldata.ptr){ + cw_log(LOG_ERR,"Can't create ElemData element: %s",strerror(errno)); + } + ((struct cw_ElemData *)(mavldata.ptr))->id=elemdef->id; + ((struct cw_ElemData *)(mavldata.ptr))->proto=elemdef->proto; + ((struct cw_ElemData *)(mavldata.ptr))->vendor=elemdef->vendor; + ((struct cw_ElemData *)(mavldata.ptr))->mand=elemdef->mand; + + result = mavl_replace(msgdata->elements_tree, &mavldata); + + if (result != &mavldata){ + cw_dbg(DBG_MOD, " adding message element %d %d %d - %s", elemdef->proto, - elemdef->id, elemdef->vendor, - handler->name - DBG_END + elemdef->id, + handler->name); + } + else{ + cw_dbg(DBG_MOD, " replaceing message element %d %d %d - %s", + elemdef->proto, + elemdef->vendor, + elemdef->id, + handler->name); + } + } return 0; @@ -203,12 +224,11 @@ int cw_msgset_add(struct cw_MsgSet * set, continue; } - DBG_START(NULL,DBG_MOD) - " Adding handler for element %d - %s - with key: %s", + cw_dbg(DBG_MOD,"Adding handler for element %d - %s - with key: %s", handler->id, handler->name, - handler->key - DBG_END + handler->key); + memcpy(copy.ptr,handler,sizeof(struct cw_ElemHandler)); @@ -244,9 +264,9 @@ int cw_msgset_add(struct cw_MsgSet * set, msg->states=msgdef->states; msg->receiver=msgdef->receiver; - DBG_START(NULL,DBG_INFO) - "Add message Type:%d - %s ",msgdef->type,msgdef->name - DBG_END + + cw_dbg(DBG_MOD, "Add message Type:%d - %s ",msgdef->type,msgdef->name); + update_msgdata(set,msg,msgdef); } diff --git a/src/cw/message_set.h b/src/cw/message_set.h index 2bfa7ac0..02222f4c 100644 --- a/src/cw/message_set.h +++ b/src/cw/message_set.h @@ -69,6 +69,8 @@ extern int cw_msgset_add(struct cw_MsgSet * set, struct cw_MsgDef messages[], struct cw_ElemHandler handlers[]); mlist_t cw_msgset_get_msg(struct cw_MsgSet * set, int type); struct cw_MsgData * cw_msgset_get_msgdata(struct cw_MsgSet *set,int type); +struct cw_ElemHandler * cw_msgset_get_elemhandler(struct cw_MsgSet * set, + int proto, int vendor, int id); #endif diff --git a/src/mod/capwap/capwap_actions_ac.c b/src/mod/capwap/capwap_actions_ac.c index 8db57944..bf686305 100644 --- a/src/mod/capwap/capwap_actions_ac.c +++ b/src/mod/capwap/capwap_actions_ac.c @@ -53,7 +53,7 @@ static struct cw_ElemHandler handlers[] = { static int discovery_request_states[] = {CAPWAP_STATE_DISCOVERY,0}; static struct cw_ElemDef discovery_request_elements[] ={ {0,0,CAPWAP_ELEM_DISCOVERY_TYPE, 1, 0}, - {0,0,CAPWAP_ELEM_WTP_MAC_TYPE, 1, 0}, +/* {0,0,CAPWAP_ELEM_WTP_MAC_TYPE, 1, 0},*/ {0,0,CAPWAP_ELEM_WTP_BOARD_DATA, 1, 0}, {0,0,0,00}