From c1f1d91b2851f0a7ce4eb23780015a42a07dee0d Mon Sep 17 00:00:00 2001
From: "7u83@mail.ru" <7u83@mail.ru@noemail.net>
Date: Sun, 25 Mar 2018 06:34:32 +0000
Subject: [PATCH] ac descriptor, struct reader
FossilOrigin-Name: 3b8718025cc9d01c66afddbc09fda047e4c78427fe342d8a800ba066eae62270
---
 libcw.project                             |  2 +-
 mod_capwap.project                        |  1 +
 src/cw/capwap.h                           | 11 ++---
 src/cw/cw.h                               | 16 +++----
 src/cw/cw_in_ac_descriptor.c              | 43 -------------------
 src/cw/cw_ktv_get.c                       |  9 ++++
 src/cw/cw_ktv_read_struct.c               | 30 +++++++++++++
 src/cw/cw_out_wtp_descriptor.c            |  5 ---
 src/cw/cw_read_ac_descriptor.c            | 52 +++++++++++------------
 src/cw/cw_read_descriptor_subelems.c      |  3 ++
 src/cw/fragman.c                          | 26 +++++++-----
 src/cw/ktv.h                              | 21 ++++++++-
 src/cw/mavl.h                             | 34 ++++-----------
 src/cw/mavl_add.c                         | 15 +++++--
 src/cw/mavl_create.c                      |  8 ++--
 src/cw/mavl_get.c                         |  1 +
 src/mod/capwap/Makefile                   |  1 +
 src/mod/capwap/capwap_actions_ac.c        |  2 +-
 src/mod/capwap/capwap_in_ac_descriptor.c  | 21 +++++++++
 src/mod/capwap/capwap_out_ac_descriptor.c | 14 +++---
 src/mod/capwap/mod_capwap.h               |  4 +-
 src/mod/cisco/capwap_cisco.h              |  2 +-
 22 files changed, 176 insertions(+), 145 deletions(-)
 delete mode 100644 src/cw/cw_in_ac_descriptor.c
 create mode 100644 src/cw/cw_ktv_read_struct.c
 create mode 100644 src/mod/capwap/capwap_in_ac_descriptor.c
diff --git a/libcw.project b/libcw.project
index 0ac641bc..cdab1ac7 100644
--- a/libcw.project
+++ b/libcw.project
@@ -129,7 +129,6 @@
       
       
       
-      
       
       
       
@@ -300,6 +299,7 @@
       
       
       
+      
     
   
   
diff --git a/mod_capwap.project b/mod_capwap.project
index dd61a7b6..baae11ed 100644
--- a/mod_capwap.project
+++ b/mod_capwap.project
@@ -23,6 +23,7 @@
         
         
         
+        
       
     
   
diff --git a/src/cw/capwap.h b/src/cw/capwap.h
index 83c1d54a..30294225 100644
--- a/src/cw/capwap.h
+++ b/src/cw/capwap.h
@@ -299,8 +299,8 @@
 #define CW_SUBELEM_WTP_BOOTLOADER_VERSION		2
 #define CW_SUBELEM_WTP_OTHERSOFTWARE_VERSION		3
 
-#define CW_SUBELEM_AC_HARDWARE_VERSION			4
-#define CW_SUBELEM_AC_SOFTWARE_VERSION			5
+#define CAPWAP_SUBELEM_AC_HARDWARE_VERSION		4
+#define CAPWAP_SUBELEM_AC_SOFTWARE_VERSION			5
 
 
 /* Frame tunnnel mode bits */
@@ -524,7 +524,7 @@ enum cw_reboot_failure_types {
 
 
 
-
+/*
 struct cwimage_data {
 	uint8_t *data;
 	uint8_t type;
@@ -546,7 +546,7 @@ extern void cw_send_image_file(struct conn *conn, FILE * infile);
 extern int cw_readmsg_configuration_status_response(uint8_t * elems, int elems_len);
 extern int cw_readmsg_configuration_update_request(uint8_t * elems, int elems_len);
 
-
+*/
 
 /* Message to text stuff */
 
@@ -561,9 +561,6 @@ extern struct cw_StrListElem mbag_item_strings[];
 
 
 
-
-
-
 #define cw_strmsg(id) cw_strlist_get_str(capwap_strings_msg,id)
 #define cw_strelem(id) cw_strlist_get_str(capwap_strings_elem,id)
 #define cw_strstate(id) cw_strlist_get_str(capwap_strings_state,id)
diff --git a/src/cw/cw.h b/src/cw/cw.h
index 9c811e55..95611ee3 100644
--- a/src/cw/cw.h
+++ b/src/cw/cw.h
@@ -345,20 +345,18 @@ extern int cw_read_wtp_descriptor_7(mavl_t mbag, struct conn *conn,
 				    struct cw_ElemHandler *eh, uint8_t * data, int len,
 				    struct cw_DescriptorSubelemDef *allowed);
 
-/*
-extern int cw_read_ac_descriptor(mbag_t store, uint8_t * data, int len,
-				 struct cw_DescriptorSubelemDef *allowed);
 
-extern int cw_read_wtp_descriptor_versions(mbag_t mbag, uint8_t * data, int len);
+int cw_read_ac_descriptor(mavl_t store,
+			   struct cw_ElemHandler *eh,
+			   struct cw_ElemHandlerParams * params,
+			   uint8_t *data, int len, 
+			struct cw_DescriptorSubelemDef *allowed);
+
+
 
 
-extern int cw_in_check_generic_resp(struct conn *conn, struct cw_action_in *a,
-				    uint8_t * data, int len, struct sockaddr *from);
 
-extern int cw_in_check_generic_req(struct conn *conn, struct cw_action_in *a,
-				   uint8_t * data, int len, struct sockaddr *from);
 
-*/
 
 /**
  * @defgroup CWELEMIN Input Handlers for Message Elements
diff --git a/src/cw/cw_in_ac_descriptor.c b/src/cw/cw_in_ac_descriptor.c
deleted file mode 100644
index 95e6cabc..00000000
--- a/src/cw/cw_in_ac_descriptor.c
+++ /dev/null
@@ -1,43 +0,0 @@
-#include "cw.h"
-
-#include "dbg.h"
-
-
-/*
-int cw_in_ac_descriptor(struct conn *conn, struct cw_action_in *a, uint8_t * data,
-			int len, struct sockaddr *from)
-{
-
-	return cw_read_ac_descriptor(conn->config,data,len,NULL);
-
-	struct cw_ac_status *status = malloc(sizeof(struct cw_ac_status));
-	if (!status)
-		return 0;
-
-	status->stations = cw_get_word(data);
-	status->limit = cw_get_word(data + 2);
-	status->active_wtps = cw_get_word(data + 4);
-	status->max_wtps = cw_get_word(data + 6);
-	status->security = cw_get_byte(data + 8);
-	status->rmac_field = cw_get_byte(data + 9);
-	status->dtls_policy = cw_get_byte(data + 11);
-
-	cw_dbg(DBG_SUBELEM,
-	       "AC Descriptor: WTPs:%d/%d, Stations:%d/%d, Security:%d, Rmac:%d, DTLS-Policy:%d",
-	       status->active_wtps, status->max_wtps, status->stations, status->limit,
-	       status->security, status->rmac_field, status->dtls_policy);
-
-
-	mbag_set_ptr(conn->incomming, CW_ITEM_AC_STATUS, status);
-
-	static struct cw_DescriptorSubelemDef allowed[] = {
-		{0,CW_SUBELEM_AC_HARDWARE_VERSION, CW_ITEM_WTP_HARDWARE_VERSION, 1024,1},
-		{0,CW_SUBELEM_AC_SOFTWARE_VERSION, CW_ITEM_WTP_SOFTWARE_VERSION, 1024,1},
-		{0,0, NULL,0, 0}
-	};
-
-	cw_read_descriptor_subelems(conn->config,"ackey" , data + 12, len - 12, allowed);
-
-	return 1;
-}
-*/
diff --git a/src/cw/cw_ktv_get.c b/src/cw/cw_ktv_get.c
index f9d62518..9dead611 100644
--- a/src/cw/cw_ktv_get.c
+++ b/src/cw/cw_ktv_get.c
@@ -1,6 +1,15 @@
+
 #include "ktv.h"
 #include "mavl.h"
 
+/**
+ * @brief Get a ktv value from a ktv store
+ * @param ktv ktv store
+ * @param key key to search for
+ * @param type type to match
+ * @return A pointer to a #cw_KTV_t element, found in the ktv store or
+ * NULL if no element with matching key/type is found.
+ */
 cw_KTV_t * cw_ktv_get(mavl_t ktv, const char *key, const cw_Type_t * type)
 {
 	cw_KTV_t search, *result;
diff --git a/src/cw/cw_ktv_read_struct.c b/src/cw/cw_ktv_read_struct.c
new file mode 100644
index 00000000..468555ad
--- /dev/null
+++ b/src/cw/cw_ktv_read_struct.c
@@ -0,0 +1,30 @@
+#include "ktv.h"
+#include "dbg.h"
+
+int cw_ktv_read_struct(mavl_t ktv,cw_KTVStruct_t * stru, const char *pkey, 
+	uint8_t * data, int len)
+{
+	char key[CW_KTV_MAX_KEY_LEN];
+	int pos, i;
+	cw_KTV_t * result;
+	
+	
+	pos=0; i=0;
+	while (stru[i].type != NULL){
+		char dbstr[100];
+		
+		sprintf(key,"%s/%s",pkey,stru[i].key);
+		result = cw_ktv_add(ktv,key,stru[i].type,data+pos,stru[i].len);
+		
+		stru[i].type->to_str(result,dbstr,100);
+		cw_dbg(DBG_ELEM_DETAIL, "Read (%d): %s: %s",pos,key,dbstr);
+	
+		if(stru[i].position == -1)
+			pos+=stru[i].len;
+		else
+			pos=stru[i].position;
+		i++;
+	}
+
+	return pos;
+}
diff --git a/src/cw/cw_out_wtp_descriptor.c b/src/cw/cw_out_wtp_descriptor.c
index 222a810a..fcf5372e 100644
--- a/src/cw/cw_out_wtp_descriptor.c
+++ b/src/cw/cw_out_wtp_descriptor.c
@@ -1,11 +1,6 @@
 #include "log.h"
 #include "capwap.h"
 #include "conn.h"
-#include "capwap.h"
-//#include "itemstore.h"
-
-#include "capwap.h"
-
 #include "cw.h"
 
 #define CW_MODE_CISCO 1
diff --git a/src/cw/cw_read_ac_descriptor.c b/src/cw/cw_read_ac_descriptor.c
index 5e2cf20a..7a746773 100644
--- a/src/cw/cw_read_ac_descriptor.c
+++ b/src/cw/cw_read_ac_descriptor.c
@@ -1,43 +1,43 @@
-#include "cw.h"
 
+#include "cw.h"
 #include "dbg.h"
 #include "ktv.h"
 
 static struct cw_DescriptorSubelemDef allowed_default[] = {
-	{0,CW_SUBELEM_AC_HARDWARE_VERSION, "ac_hardware_versision", 1024,1},
-	{0,CW_SUBELEM_AC_SOFTWARE_VERSION, "ac_software_version", 1024,1},
+	{0,CAPWAP_SUBELEM_AC_HARDWARE_VERSION, "hardware", 1024,1},
+	{0,CAPWAP_SUBELEM_AC_SOFTWARE_VERSION, "software", 1024,1},
 	{0,0, NULL,0, 0}
 };
 
+cw_KTVStruct_t acstatus [] = {
+	/* type	        key	   	len,	pos */ 
+	{CW_TYPE_WORD, "stations", 	2,	-1},
+	{CW_TYPE_WORD, "station-limit", 2,	-1},
+	{CW_TYPE_WORD, "avtive-wtps",	2,	-1},
+	{CW_TYPE_WORD, "max-wtps",	2,	-1},
+	{CW_TYPE_BYTE, "security",	1,	-1},
+	{CW_TYPE_BYTE, "r-mac-field",	1,	-1},
+	{CW_TYPE_BYTE, "reserved1",	1,	-1},
+	{CW_TYPE_BYTE, "dtls-policy",	1,	-1},
+	{NULL,NULL,0,0}
+};
 
-int cw_read_ac_descriptor(mavl_t store, uint8_t *data, int len, 
-		struct cw_DescriptorSubelemDef *allowed)
+
+
+
+int cw_read_ac_descriptor(mavl_t store,
+			   struct cw_ElemHandler *eh,
+			   struct cw_ElemHandlerParams * params,
+			   uint8_t *data, int len, 
+			struct cw_DescriptorSubelemDef *allowed)
 {
-	char key[CW_KTV_MAX_KEY_LEN];
-	cw_KTV_t * stations, *limit;
-
-	stations = cw_ktv_add(store,"ac-descriptor/stations",CW_TYPE_WORD,data,4);
-
-/*	status->stations = cw_get_word(data);
-	status->limit = cw_get_word(data + 2);
-	status->active_wtps = cw_get_word(data + 4);
-	status->max_wtps = cw_get_word(data + 6);
-	status->security = cw_get_byte(data + 8);
-	status->rmac_field = cw_get_byte(data + 9);
-	status->dtls_policy = cw_get_byte(data + 11);
-
-	cw_dbg(DBG_SUBELEM,
-	       "AC Descriptor: WTPs:%d/%d, Stations:%d/%d, Security:%d, Rmac:%d, DTLS-Policy:%d",
-	       status->active_wtps, status->max_wtps, status->stations, status->limit,
-	       status->security, status->rmac_field, status->dtls_policy);
-*/
-/*	mbag_set_ptr(store, CW_ITEM_AC_STATUS, status);*/
-
+	
+	cw_ktv_read_struct(params->conn->remote_cfg,acstatus,eh->key,data,len);
 
 	if (!allowed)
 		allowed=allowed_default;
 
-	return cw_read_descriptor_subelems(store, "key", data + 12, len - 12, allowed);
+	return cw_read_descriptor_subelems(store, eh->key, data + 12, len - 12, allowed);
 	
 }
 
diff --git a/src/cw/cw_read_descriptor_subelems.c b/src/cw/cw_read_descriptor_subelems.c
index 82dfc53a..c2627cac 100644
--- a/src/cw/cw_read_descriptor_subelems.c
+++ b/src/cw/cw_read_descriptor_subelems.c
@@ -44,6 +44,9 @@ int cw_read_descriptor_subelems(mavl_t cfg, const char * parent_key,
 		
 		/* search sub-element */
 		for (i = 0; elems[i].maxlen; i++) {
+			
+			printf("subcmp: %d %d\n",elems[i].type,subtype);
+			
 			if (elems[i].type == subtype /* && elems[i].vendor_id==vendor_id*/)
 				break;
 		}
diff --git a/src/cw/fragman.c b/src/cw/fragman.c
index 47423f60..92d80054 100644
--- a/src/cw/fragman.c
+++ b/src/cw/fragman.c
@@ -80,9 +80,10 @@ static struct frag * frag_get(struct frag * frags, int fragid)
 static struct frag * frag_new(struct frag * frags, int fragid)
 {
         struct timespec t;
+	int i;
 	clock_gettime(CLOCK_REALTIME,&t);
 
-	int i;
+
 	for (i=0; iFRAG_TTL) ){
 
@@ -126,19 +127,22 @@ uint8_t * fragman_add(frag_t * frags, uint8_t *packet, int hlen, int payloadlen)
 {
 	struct frag * f;
 	uint32_t val0,val1;
-
+	int fragid,fragoffset;
+	int dst;
+	int ti;
+	
 	/* read the transport header dword 0,
 	 * contains hlen*/	
 	val0 = ntohl(*((uint32_t*)packet));
-//	int hlen = (val0 >> 19) & 0x1f;
+/*	int hlen = (val0 >> 19) & 0x1f;*/
 
 	/* read the transport header dword 1,
 	 * contains fragid and fragoffset */	
 	val1 = ntohl(*(((uint32_t*)packet)+1));
-	int fragid = val1>>16;
-	int fragoffset=(val1 >>3) & 0x1fff;
+	fragid = val1>>16;
+	fragoffset=(val1 >>3) & 0x1fff;
 
-//	printf("Fragid = %i, offset = %i\n",fragid,fragoffset);
+/*//	printf("Fragid = %i, offset = %i\n",fragid,fragoffset);*/
 	
 	/* determine size of payload */
 /*	int payloadlen = len - hlen*4;
@@ -160,7 +164,7 @@ uint8_t * fragman_add(frag_t * frags, uint8_t *packet, int hlen, int payloadlen)
 
 	errno = 0;
 
-	int dst = fragoffset*8;
+	dst = fragoffset*8;
 
 	/* copy fragment*/
 	if (dst + payloadlen < FRAG_MAXSIZE) {
@@ -172,9 +176,9 @@ uint8_t * fragman_add(frag_t * frags, uint8_t *packet, int hlen, int payloadlen)
 		f->bytesneeded=dst+payloadlen;
 	}
 
-	int ti;
+	
 	for (ti=0; ti<16; ti++){
-//		printf("%02X ",(f->buffer+4)[ti]);
+/*//		printf("%02X ",(f->buffer+4)[ti]);*/
 
 	}
 
@@ -182,12 +186,12 @@ uint8_t * fragman_add(frag_t * frags, uint8_t *packet, int hlen, int payloadlen)
 	if (f->bytesneeded>0 && f->bytesneeded<=f->bytesreceived){
 		uint8_t * r=f->buffer;
 		f->buffer=0;
-//		printf("last bytes need %i\n",f->bytesneeded);
+/*//		printf("last bytes need %i\n",f->bytesneeded);*/
 		*((uint32_t*)(r))=f->bytesneeded;
 		return r; 
 	}
 
-//	printf("Fragman bytes needed: %i, received  %i\n",f->bytesneeded,f->bytesreceived);
+/*//	printf("Fragman bytes needed: %i, received  %i\n",f->bytesneeded,f->bytesreceived);*/
 	return NULL;
 }
 
diff --git a/src/cw/ktv.h b/src/cw/ktv.h
index 3b181230..5151de5e 100644
--- a/src/cw/ktv.h
+++ b/src/cw/ktv.h
@@ -20,11 +20,19 @@
 
 #define CW_KTV_MAX_KEY_LEN 1024
 
+/**
+ * @struct cw_KTV
+ * @file ktv.h
+ * @brief Structure to store a key-type-value element.
+ */
 struct cw_KTV {
+	/** The key for this element. A string. */
 	char *key;
+	/** Teh type of this element. */
 	const struct cw_Type *type;
+	/** The value for this element */
 	union {
-		uint32_t dword;
+		uint32_t dword;	
 		uint16_t word;
 		uint8_t byte;
 		void *ptr;
@@ -72,6 +80,17 @@ struct cw_Type {
 };
 typedef struct cw_Type cw_Type_t;
 
+
+struct cw_KTVStruct {
+	const struct cw_Type * type;
+	const char * key;
+	int len;
+	int position;
+};
+typedef struct cw_KTVStruct cw_KTVStruct_t;
+int cw_ktv_read_struct(mavl_t ktv,cw_KTVStruct_t * stru, const char *pkey, 
+	uint8_t * data, int len);
+
 extern const struct cw_Type cw_type_byte;
 extern const struct cw_Type cw_type_word;
 extern const struct cw_Type cw_type_dword;
diff --git a/src/cw/mavl.h b/src/cw/mavl.h
index 8bd2b6ac..a668423f 100644
--- a/src/cw/mavl.h
+++ b/src/cw/mavl.h
@@ -25,6 +25,9 @@
 /**
  * @addtogroup DATAMGMT
  * @{
+ * 
+ * @defgroup MAVL Mavl Tree
+ * @{
  */
 
 
@@ -40,26 +43,13 @@
 
 
 
-
-/**
- * @defgroup MAVL_CONSTANTS Constants
- * @{
- */
-
 /** Maximum AVL Tree depth.
     The number of nodes is calculated by 2^depth.
     So a value of 32 should be enough for around 4
     billion nodes. */
 #define MAVL_MAX_DEPTH	32
 
-/**
- * @}
- */
 
-/**
- * @addtogroup MAVLStructures Structures
- * @{
- */
 
 
 /**
@@ -97,9 +87,6 @@ struct mavl {
 	size_t data_size;
 };
 
-/**
- * @}
- */
 
 /**
  * MAVL AVL Tree type
@@ -107,10 +94,6 @@ struct mavl {
 typedef struct mavl * mavl_t;
 
 
-/**
- * @defgroup MAVL_FUNCTIONS Functions
- * @{
- */
 
 /**
  * @param node node 
@@ -121,6 +104,7 @@ struct mavl *mavl_create ( int ( *cmp ) ( const void *, const void * ),
                            void ( *del ) ( void * ), size_t data_size );
 
 void *mavl_add ( struct mavl *t, const void *data, int *exists );
+
 /*void *mavl_add ( struct mavl *t,  const void *data );*/
 void * mavl_get ( struct mavl *t , const void *data );
 void *mavl_del ( struct mavl *t, const void *data );
@@ -148,9 +132,6 @@ int mavl_foreach_from_lr ( struct mavl *t, struct mavlnode *n, void *data,
 
 
 
-/**
- * @}
- */
 
 
 
@@ -159,7 +140,7 @@ void *mavl_replace_data ( struct mavl *t, void *data, int len );
 
 
 /**
- * An alias gor #mavl_get
+ * This macro is an alias for #mavl_get
  */
 #define mavl_find(t,d) mavl_get(t,d)
 
@@ -292,9 +273,10 @@ void * mavl_add_ptr ( mavl_t tree, const void *ptr );
 #define mavliter_get_str(iter) ((char*)(mavliter_get_ptr(iter)))
 
 /**
+ * @} MAVL
+ * 
+ * @} DATAMGMT
  * 
- * @}
- * datamanag
  */
 
 
diff --git a/src/cw/mavl_add.c b/src/cw/mavl_add.c
index fd8bbed1..87627b34 100644
--- a/src/cw/mavl_add.c
+++ b/src/cw/mavl_add.c
@@ -1,3 +1,8 @@
+/**
+ * @file
+ * @brief Implementation of mavl_add
+ */
+
 #include "mavl.h"
 
 static struct mavlnode *mavlnode_create ( struct mavl *t, const void *data )
@@ -179,20 +184,21 @@ static int mavl_add0 ( struct mavl *t, struct mavlnode **parent, const void ** d
 
 
 /**
+ * @brief mavl add function
  * Add an element to an AVL tree
- *
  * @param t mavl
  * @param data pointer to the element to add
  * @param exists pointer to an interger vairable which wil be set to 1, if
  * the element to add already exists in the tree. If the element did't
  * exist, the variable ist to 0.
+
  * @return A pointer to the element in the tree. If the element was added, 
  * it the pointer to newly created element. If the element had already existed,
  * the pointer points to the existing element. mavl_add returns thero, if 
  * something else went wrong. Therefore consult errno.
- * @example mavl_add_example.c
+ * 
+ * 
  */
-
 void *mavl_add ( struct mavl *t, const void *data, int *exists )
 {
 	const void * d;
@@ -232,3 +238,6 @@ void *mavl_add ( struct mavl *t, const void *data)
 	return mavl_add_exists(t,data,NULL);
 }
 */
+
+
+ 
\ No newline at end of file
diff --git a/src/cw/mavl_create.c b/src/cw/mavl_create.c
index bf01301c..646c544a 100644
--- a/src/cw/mavl_create.c
+++ b/src/cw/mavl_create.c
@@ -19,8 +19,6 @@
 /**
  *@file
  *@brief Implementation of mavl_create
- *@addtogroup MavlFunctions 
- *@{
  */
  
 #include "mavl.h"
@@ -30,7 +28,9 @@
  * @param cmp pointer to compare function
  * @param del pointer to delete function which is called when an element 
  * will be deletet
- * @return pointer to a #mavl struct
+ * @param dta_size size of a data element
+ * @return pointer to a #mavl struct. If the return value is NULL something
+ * went wrong, and you should consult errno to get details.
  */
 struct mavl *mavl_create(int (*cmp) (const void *, const void  *),
 			       void (*del) (void *), size_t data_size)
@@ -46,5 +46,5 @@ struct mavl *mavl_create(int (*cmp) (const void *, const void  *),
 	return t;
 }
 
-/**@}*/
+
 
diff --git a/src/cw/mavl_get.c b/src/cw/mavl_get.c
index 8fe76d4a..aded1f56 100644
--- a/src/cw/mavl_get.c
+++ b/src/cw/mavl_get.c
@@ -25,6 +25,7 @@
 
 /**
  * Get an AVL tree element.
+ * @param t pointer to mavl_t
  * @param data Element to get
  * @return pointer to element or NULL if not found. 
  */ 
diff --git a/src/mod/capwap/Makefile b/src/mod/capwap/Makefile
index 6c423d62..de137c80 100644
--- a/src/mod/capwap/Makefile
+++ b/src/mod/capwap/Makefile
@@ -5,6 +5,7 @@ OBJS=\
 	mod_capwap_ac.o \
 	capwap_actions_ac.o \
 	capwap_in_wtp_board_data.o \
+	capwap_in_ac_descriptor.o \
 	capwap_out_wtp_board_data.o \
 	capwap_out_ac_descriptor.o \
 	capwap_out_get_session_id.o \
diff --git a/src/mod/capwap/capwap_actions_ac.c b/src/mod/capwap/capwap_actions_ac.c
index 9f504416..51500f7a 100644
--- a/src/mod/capwap/capwap_actions_ac.c
+++ b/src/mod/capwap/capwap_actions_ac.c
@@ -115,7 +115,7 @@ static struct cw_ElemHandler handlers[] = {
 		0,0,					/* min/max length */
 		NULL,					/* type */
 		CW_KEY_AC_DESCRIPTOR,			/* Key */
-		NULL,					/* get */
+		capwap_in_ac_descriptor,		/* get */
 		capwap_out_ac_descriptor		/* put */
 	}
 	,
diff --git a/src/mod/capwap/capwap_in_ac_descriptor.c b/src/mod/capwap/capwap_in_ac_descriptor.c
new file mode 100644
index 00000000..aa23afbb
--- /dev/null
+++ b/src/mod/capwap/capwap_in_ac_descriptor.c
@@ -0,0 +1,21 @@
+
+#include "cw/cw.h"
+
+#include "cw/dbg.h"
+
+#include "cw/vendors.h"
+
+int capwap_in_ac_descriptor(struct cw_ElemHandler *eh, 
+			struct cw_ElemHandlerParams *params, 
+			uint8_t * data, int len)
+{
+	static struct cw_DescriptorSubelemDef allowed[] = {
+		{0,CAPWAP_SUBELEM_AC_HARDWARE_VERSION, "hardware", 1024,1},
+		{0,CAPWAP_SUBELEM_AC_SOFTWARE_VERSION, "software", 1024,1},
+		{0,0, NULL,0, 0}
+	};
+
+
+	return cw_read_ac_descriptor(params->conn->remote_cfg,eh,params,data,len,allowed);
+
+}
diff --git a/src/mod/capwap/capwap_out_ac_descriptor.c b/src/mod/capwap/capwap_out_ac_descriptor.c
index 40613004..3b23c8c0 100644
--- a/src/mod/capwap/capwap_out_ac_descriptor.c
+++ b/src/mod/capwap/capwap_out_ac_descriptor.c
@@ -1,12 +1,11 @@
 
 #include "cw/log.h"
+#include "cw/dbg.h"
 #include "cw/conn.h"
 
 
 
 #include "cw/capwap.h"
-
-
 #include "cw/cw.h"
 #include "cw/ktv.h"
 #include "cw/keys.h"
@@ -54,7 +53,7 @@ static int put_ac_status(mavl_t global, mavl_t local, uint8_t *dst, const char *
 int capwap_out_ac_descriptor(struct cw_ElemHandler * eh, 
 		struct cw_ElemHandlerParams * params, uint8_t * dst)
 {
-	int len;
+	int len,l;
 	uint8_t *d = dst+4;
 	char key[CW_KTV_MAX_KEY_LEN];
 
@@ -64,14 +63,17 @@ int capwap_out_ac_descriptor(struct cw_ElemHandler * eh,
 
 	sprintf(key,"%s/%s",eh->key,CW_SKEY_HARDWARE);
 	d+=cw_write_descriptor_subelem (d, params->conn->local_cfg,
-                                 CW_SUBELEM_AC_HARDWARE_VERSION, key);
+                                 CAPWAP_SUBELEM_AC_HARDWARE_VERSION, key);
  
 	sprintf(key,"%s/%s",eh->key,CW_SKEY_SOFTWARE);
 	d+=cw_write_descriptor_subelem (d, params->conn->local_cfg,
-                                 CW_SUBELEM_AC_HARDWARE_VERSION, key);
+                                 CAPWAP_SUBELEM_AC_SOFTWARE_VERSION, key);
 
 	len = d-dst-4;
 
-	return len + cw_put_elem_hdr(dst,eh->id,len);
+	l = len + cw_put_elem_hdr(dst,eh->id,len);
+	cw_dbg_elem(DBG_ELEM_OUT,params->conn,params->msgdata->type,eh,dst,l);
+
+	return l;
 
 }
diff --git a/src/mod/capwap/mod_capwap.h b/src/mod/capwap/mod_capwap.h
index b096e515..7269d3ef 100644
--- a/src/mod/capwap/mod_capwap.h
+++ b/src/mod/capwap/mod_capwap.h
@@ -27,7 +27,9 @@ int capwap_in_capwap_control_ip_address(struct cw_ElemHandler *eh,
 		struct cw_ElemHandlerParams *params, 
 			uint8_t * data,	 int len);
 
-
+int capwap_in_ac_descriptor(struct cw_ElemHandler *eh, 
+			struct cw_ElemHandlerParams *params, 
+			uint8_t * data, int len);
 
 
 /*
diff --git a/src/mod/cisco/capwap_cisco.h b/src/mod/cisco/capwap_cisco.h
index f41e82b7..b2714fe4 100644
--- a/src/mod/cisco/capwap_cisco.h
+++ b/src/mod/cisco/capwap_cisco.h
@@ -34,7 +34,7 @@
 #define CW_CISCO_MWAR_ADDR			LW_ELEM_AC_ADDRESS			/* 2 */
 #define CW_CISCO_RAD				3
 #define CW_CISCO_RAD_SLOT			4
-#define CW_CISCO_RAD_NAME			LW_ELEM_WTP_NAME			/* 5 */
+#define CW_CISCO_RAD_NAME			LWAPP_ELEM_WTP_NAME			/* 5 */
 #define	CW_CISCO_MWAR				LW_ELEM_AC_DESCRIPTOR			/* 6 */
 #define CW_CISCO_ADD_WLAN			LW_ELEM_80211_ADD_WLAN			/* 7 */
 #define CW_CISCO_WTP_RADIO_CFG			8