diff --git a/src/capwap/cw_in_wtp_descriptor.c b/src/capwap/cw_in_wtp_descriptor.c new file mode 100644 index 00000000..04eae57f --- /dev/null +++ b/src/capwap/cw_in_wtp_descriptor.c @@ -0,0 +1,111 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + + +#include "capwap.h" +#include "capwap_items.h" + +#include "wtpinfo.h" + +#include "cw_util.h" +#include "cw_log.h" + + + + +static int readelem_wtp_descriptor(struct conn *conn, struct cw_action_in *a, uint8_t *data, int len, int cq) +{ + + if (len<6) + return -1; + + cw_itemstore_t itemstore = conn->itemstore; + + cw_itemstore_set_byte(itemstore,CW_ITEM_WTP_MAX_RADIOS,cw_get_byte(data)); + cw_itemstore_set_byte(itemstore,CW_ITEM_WTP_RADIOS_IN_USE,cw_get_byte(data+1)); + + int ncrypt = cw_get_byte(data+2); + int i; + if (ncrypt == 0 ){ + /* non-conform */ + cw_dbg(DBG_CW_RFC,"Non-standard-conform WTP descriptor detected (See RFC 5415)"); + if (!cq) + i=3; + else + i=4; + } + else{ + i=ncrypt*3+3; + } + + do { + if (i+8>len) + { + cw_dbg(DBG_ELEM_ERR,"WTP descriptor subelement to long, length=%d>%d",i+8,len); + return -1; + } + + uint32_t vendor_id=cw_get_dword(data+i); //ntohl(*((uint32_t*)(msgelem+i))); + + uint32_t val = cw_get_dword(data+i+4); + int subtype= (val>>16)&0xffff; + int sublen = val&0xffff; + i+=8; + + if (sublen+i>len){ + cw_dbg(DBG_ELEM_ERR,"WTP descriptor subelement too long, length = %d",sublen); + return -1; + } + + cw_dbg(DBG_ELEM,"Reading WTP descriptor subelement, type=%d,len=%d",subtype,sublen); + + switch(subtype){ + case CW_SUBELEM_WTP_HARDWARE_VERSION: + cw_itemstore_set_dword(itemstore,CW_ITEM_WTP_HARDWARE_VENDOR,vendor_id); + cw_itemstore_set_bstrn(itemstore,CW_ITEM_WTP_HARDWARE_VERSION,data+i,sublen); + break; + case CW_SUBELEM_WTP_SOFTWARE_VERSION: + cw_itemstore_set_dword(itemstore,CW_ITEM_WTP_SOFTWARE_VENDOR,vendor_id); + cw_itemstore_set_bstrn(itemstore,CW_ITEM_WTP_SOFTWARE_VERSION,data+i,sublen); + break; + case CW_SUBELEM_WTP_BOOTLOADER_VERSION: + cw_itemstore_set_dword(itemstore,CW_ITEM_WTP_BOOTLOADER_VENDOR,vendor_id); + cw_itemstore_set_bstrn(itemstore,CW_ITEM_WTP_BOOTLOADER_VERSION,data+i,sublen); + break; + default: + cw_dbg(DBG_ELEM_ERR,"Unknown WTP descriptor subelement, type = %d",subtype); + break; + } + i+=sublen; + + }while(iresp_buffer; + int hbytes = cw_get_hdr_msg_offset(req); + memcpy(buffer,req,hbytes); + + uint8_t * msgptr = req+hbytes; + uint8_t * dmsgptr = buffer+hbytes; + + 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); + + +} diff --git a/src/capwap/cw_out_ac_descriptor.c b/src/capwap/cw_out_ac_descriptor.c new file mode 100644 index 00000000..0de0fcf0 --- /dev/null +++ b/src/capwap/cw_out_ac_descriptor.c @@ -0,0 +1,68 @@ +#include "cw_log.h" +#include "conn.h" + +#include "itemstore.h" +#include "capwap_items.h" +#include "capwap.h" + + +int cw_put_subelem_version(uint8_t *dst,uint16_t subelem_id, uint32_t vendor_id,bstr16_t data) +{ +printf("Vendor putter %d\n",vendor_id); + + uint8_t *d=dst; + d += cw_put_dword(d,vendor_id); + d += cw_put_dword(d, (subelem_id<<16) | bstr16_len(data)); + d += cw_put_data(d,bstr16_data(data),bstr16_len(data)); + return d-dst; +} + + + +int cw_out_ac_descriptor(struct conn *conn,uint32_t elem_id,uint8_t *dst,struct cw_item * item) +{ + + uint8_t *d = dst+4; + struct cw_item * i; + i = cw_itemstore_get(conn->local,CW_ITEM_AC_STATUS); + + if (!i) { + cw_log(LOG_ERR,"Can't send AC Descriptor, no AC Status Item found"); + return 0; + } + + struct cw_ac_status *s = (struct cw_ac_status*)(i->data); + + d += cw_put_dword (d, (s->stations << 16) | (s->limit) ); + d += cw_put_dword (d, (s->active_wtps <<16) | (s->max_wtps) ); + d += cw_put_dword (d, (s->security<<24) | (s->rmac_field<<16) | (s->dtls_policy)); + + + + i = cw_itemstore_get(conn->local,CW_ITEM_AC_HARDWARE_VERSION); + + if ( i ) { + d += cw_put_subelem_version(d,CW_SUBELEM_AC_HARDWARE_VERSION,*((uint32_t*)(i->data)),i->data+4); + } + else { + cw_dbg(DBG_ELEM_ERR, "Can't send hard version in AC descriptor, not set."); + } + + + i = cw_itemstore_get(conn->local,CW_ITEM_AC_SOFTWARE_VERSION); + + if ( i ) { + d += cw_put_subelem_version(d,CW_SUBELEM_AC_SOFTWARE_VERSION,*((uint32_t*)(i->data)),i->data+4); + } + else { + cw_dbg(DBG_ELEM_ERR, "Can't send software version in AC descriptor, not set."); + } + + int len = d-dst-4; + + return len + cw_put_elem_hdr(dst,CW_ELEM_AC_DESCRIPTOR,len); + +} + + + diff --git a/src/capwap/cw_out_ac_name.c b/src/capwap/cw_out_ac_name.c new file mode 100644 index 00000000..a13ed8f5 --- /dev/null +++ b/src/capwap/cw_out_ac_name.c @@ -0,0 +1,9 @@ + +#include "capwap.h" + +int cw_out_ac_name(uint8_t * dst,cw_item *item) +{ + uint8_t *data = item->data; + int len = cw_put_data(dst+4,data,strlen(data)); + return len + cw_put_elem_hdr(str,CW_ELEM_AC_NAME,len); +} diff --git a/src/capwap/cw_out_capwap_control_ip_addrs.c b/src/capwap/cw_out_capwap_control_ip_addrs.c new file mode 100644 index 00000000..321bd27a --- /dev/null +++ b/src/capwap/cw_out_capwap_control_ip_addrs.c @@ -0,0 +1,61 @@ + +#include "cw_log.h" + +#include "capwap.h" +#include "aciplist.h" +#include "sock.h" + + +static int put_ip(void *priv, void *data) +{ + uint8_t ** dptr = (uint8_t **)priv; + cw_acip_t *acip=(cw_acip_t*)data; + + uint8_t * dst = *dptr; + + uint8_t *d = dst+4; + + d+=cw_put_sockaddr(d,&acip->ip); + d+=cw_put_word(d,acip->wtp_count); + + int fam = sock_addrfamily(&acip->ip); + int elem_id=-1; + switch (fam) { + case AF_INET: + elem_id = CW_ELEM_CAPWAP_CONTROL_IPV4_ADDRESS; + break; + case AF_INET6: + elem_id = CW_ELEM_CAPWAP_CONTROL_IPV6_ADDRESS; + break; + default: + cw_log(LOG_ERR,"Unknown adress family %d",fam); + break; + } + + if (elem_id != -1 ) { + d+=cw_put_elem_hdr(dst,elem_id,d-dst-4); + *dptr = d-4; + } + + return 1; +} + + +int cw_out_capwap_control_ip_addrs(struct conn *conn,uint32_t elem_id,uint8_t *dst,struct cw_item * item) +{ + if ( !item ) { + cw_log(LOG_ERR, "Can't send CAPWAP Local IPv4/IPv6 Address, not found"); + return 0; + } + + + cw_aciplist_t aciplist = (cw_aciplist_t) cw_item_get_data_ptr(item); + + + uint8_t *d = dst; + cw_aciplist_foreach(aciplist, put_ip, &d); + + cw_item_release_data_ptr(item,aciplist); + return d-dst; +} + diff --git a/src/capwap/cw_out_generic.c b/src/capwap/cw_out_generic.c new file mode 100644 index 00000000..cd2c27d8 --- /dev/null +++ b/src/capwap/cw_out_generic.c @@ -0,0 +1,35 @@ + + + +#include "capwap.h" +#include "capwap_items.h" + + +int cw_put_item(uint8_t *dst,struct cw_item*item) +{ + switch (item->type){ + case CW_ITEMTYPE_STR: + printf("Outing str %s\n",item->data); + return cw_put_data(dst,item->data,strlen( (char*)item->data)); + case CW_ITEMTYPE_BYTE: + return cw_put_byte(dst,item->byte); + case CW_ITEMTYPE_WORD: + return cw_put_word(dst,item->word); + case CW_ITEMTYPE_DWORD: + return cw_put_word(dst,item->dword); + } + + return 0; +} + +int cw_out_generic(struct conn *conn,uint32_t elem_id,uint8_t *dst,struct cw_item * item) +{ + int len; + if ( !item ) + len=0; + else + len = cw_put_item(dst+4,item); + return len + cw_put_elem_hdr(dst,elem_id,len); +} + + diff --git a/src/capwap/cw_strnelem.c b/src/capwap/cw_strnelem.c new file mode 100644 index 00000000..e69de29b diff --git a/src/capwap/dbg.h b/src/capwap/dbg.h new file mode 100644 index 00000000..6944bf58 --- /dev/null +++ b/src/capwap/dbg.h @@ -0,0 +1,18 @@ +#ifndef __DBG_H +#define __DBG_H + + + +void cw_dbg_elem_(int msg, int msgelem, const uint8_t * msgbuf, int len); + + +#ifdef WITH_CW_LOG_DEBUG + + #define cw_dbg_elem(msgtype,msgelemtype,msgbuf,msglen) cw_dbg_elem_(msgtype,msgelemtype,msgbuf,msglen) + +#else + + #define cw_dbg_elem(...) +#endif + +#endif