renamed capwap directory to cw.

FossilOrigin-Name: 8a43dd9d05a4cb73210243ddd8df2a26f16c7ef2c4d4e36ab446de1f65d88223
This commit is contained in:
7u83@mail.ru
2016-03-03 19:46:20 +00:00
parent 4d242d1b44
commit f4ebe841a5
309 changed files with 116 additions and 116 deletions

2303
src/cw/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

339
src/cw/Makefile Normal file
View File

@ -0,0 +1,339 @@
include ../CapwapConfig.mak
include ../Macros.mak
ifndef CC
CC=gcc
endif
ifndef AR
AR = ar
endif
#ifndef ARCH
# ARCH = $(shell $(CC) -dumpmachine)
#endif
#OPENSSLINC=$(OPENSSLINC)
#../contrib/openssl-1.0.1i/include
NAME=libcw.a
LIBDIR=../lib/$(ARCH)
SOCKOBJS=\
sock_create.o\
sock_copyaddr.o\
sock_strtoaddr.o\
sock_cmpaddr.o\
sock_addrlen.o \
sock_mwait.o\
sock_addrtostr.o \
sock_setport.o \
sock_getport.o \
sock_getifaddr.o \
sock_getifhwaddr.o \
sock_hwaddrtostr.o \
sock_set_recvtimeout.o \
sock_getbroadcastaddr.o \
sock_addrinit.o \
sock_set_dontfrag.o \
sock_get_primary_if.o \
sock_receive.o \
sock_getifinfo.o \
LOGOBJS=log.o \
log_syslog.o \
log_file.o \
dbg_strings.o\
dbg.o \
WTPINFOOBJS =\
#wtpinfo_print.o
#wtpinfo_set_location.o \
wtpinfo_lwreadelem_wtp_descriptor.o \
UTILOBJS= \
cw_setstr.o \
cw_is_printable.o \
cw_rand.o \
stravltree.o \
intavltree.o \
cw_util.o \
send.o \
cw_read_wtp_descriptor.o \
cw_read_wtp_descriptor_7.o \
cw_read_wtp_descriptor_versions.o
MAVLOBJS= \
mavl_del.o \
mavl_add.o \
mavl_create.o\
mavl_get.o\
mavl_del_all.o\
mavliter_seek.o \
mavliter_next.o \
mavl_get_node.o \
mavl_foreach.o \
mavl_foreach_lr.o \
mavl_merge.o \
mavl_create_conststr.o \
mlist.o \
utf8.o \
cw_load_file.o \
cw_save_file.o
# cw_foreach_msgelem.o \
# mavl.o \
# LWAPP objs
LWAPPOBJS = \
lw_checksum.o \
lw_put_ac_descriptor.o \
lw_put_cisco_path_mtu.o \
lw_readelem_vendor_specific.o \
lw_elem_id_to_str.o \
lw_msg_id_to_str.o \
lw_cisco_id_to_str.o \
lw_put_sockaddr.o \
lw_put_image_data.o
#lw_put_80211_wtp_wlan_radio_configuration.o \
# lw_readelem_wtp_name.o \
lw_readelem_wtp_board_data.o \
cw_log_debug.o \
lw_vendor_id_to_str.o \
# LWAPP cisco vendor specific objs
LWAPPCISCOOBJS = \
lw_addelem.o
# cw_tohex.o\
#capwap_parse_ctrlhdr.o \
CAPWAPOBJS= \
aciplist.o \
lwmsg_init.o \
hdr_print.o \
cw_cisco_id_to_str.o\
cw_strlist_get_str.o \
cw_strlist_get_id.o \
capwap_strings_msg.o \
capwap_strings_elem80211.o\
acpriolist.o\
capwap_strings_state.o \
capwap_strings_vendor.o \
capwap_strings_elem.o \
cw_in_vendor_specific_payload.o \
cw_in_wtp_board_data.o \
cw_in_check_disc_req.o \
cw_in_check_chng_state_evnt_req.o\
cw_in_check_disc_resp.o\
cw_in_check_cfg_update_req.o\
cw_in_check_join_req.o \
cw_in_check_cipwap_join_req.o \
cw_in_check_join_resp.o \
cw_in_check_img_data_req_ac.o \
cw_in_check_img_data_req_wtp.o \
cw_in_check_img_data_resp.o \
cw_out_generic.o \
cw_out_ac_descriptor.o \
cw_out_wtp_descriptor.o \
cw_in_cisco_image_identifier.o\
cw_out_radio_operational_state.o\
cw_in_ac_descriptor.o\
cw_out_capwap_local_ip_address.o\
cw_out_capwap_control_ip_addr_list.o \
cw_in_capwap_control_ipv4_address.o\
cw_in_radio_administrative_state.o \
cw_in_radio_administrative_state_wtp.o \
strheap.o \
cw_check_missing_mand.o \
md5sum.o \
format.o \
cw_in_cisco_add_wlan.o
#
# SSL objects
#
ifeq ($(WITH_OPENSSL),1)
CFLAGS+=$(OPENSSL_CFLAGS)
CFLAGS+=-DWITH_OPENSSL
DTLSOBJS += dtls_openssl.o \
dtls_openssl_accept.o \
dtls_openssl_connect.o \
dtls_openssl_get_cipher.o \
dtls_openssl_bio.o
endif
ifeq ($(WITH_GNUTLS),1)
CFLAGS+=$(GNUTLS_CFLAGS)
CFLAGS+=-DWITH_GNUTLS
DTLSOBJS+= dtls_gnutls.o \
dtls_gnutls_accept.o \
dtls_gnutls_connect.o \
dtls_gnutls_bio.o \
dtls_gnutls_get_cipher.o \
dtls_gnutls_get_peers_cert.o
endif
DTLSOBJS+=dtls_bio.o
CONNOBJS= conn_create.o \
conn_process_packet.o \
conn_process_packet2.o \
conn_q_add_packet.o \
conn_q_get_packet.o \
conn_q_recv_packet.o \
conn_recv_packet.o \
conn_destroy.o \
connlist.o \
conn_create_noq.o \
conn_init.o \
conn_send_packet.o \
# conn_send_msg.o
#conn_get_message.o \
# conn_send_response.o \
# cw_prepare_configuration_status_request.o \
# cw_prepare_change_state_event_request.o \
conn_prepare_configuration_update_request.o \
BSTROBJS= bstr_create.o \
bstr_create_from_cfgstr.o \
bstr_replace.o \
bstr_to_str.o \
bstr16cfgstr.o \
bstr16_create_from_str.o \
bstr_create_from_str.o \
vendorstr_create_from_str.o
FRAGOBJS=fragman.o
CWACTION=action.o \
capwap_actions_ac.o \
capwap_actions_wtp.o \
capwap_80211_actions_wtp.o \
capwap_80211_actions_ac.o \
cw_in_generic.o \
cw_in_generic2.o \
cw_in_wtp_descriptor.o \
cw_out_wtp_board_data.o \
cw_out_ac_name_with_priority.o \
cw_in_ac_name_with_priority.o \
cw_out_image_data.o \
cipwap_actions_ac.o \
cipwap_actions_wtp.o \
cipwap_strings_elem.o \
capwap_strings_result.o\
cw_put_msg.o \
capwap_action_helpers.o \
cw_put_image_data.o \
cisco.o \
mbag.o\
mbag_type_word.o\
mbag_type_byte.o\
mbag_type_vendorstr.o\
mbag_type_sockaddr.o\
mbag_type_dword.o\
mbag_type_bstr16.o\
mbag_type_mbag.o\
radio.o \
cw_out_radio_info.o \
capwap_items.o \
item.o
# cw_process_msg.o \
# item_strings.o \
OBJS=$(CONNOBJS) $(FRAGOBJS) $(SOCKOBJS) $(CAPWAPOBJS) $(WTPINFOOBJS) \
$(LOGOBJS) $(UTILOBJS) $(DTLSOBJS) $(BSTROBJS) \
$(LWAPPOBJS) \
$(LWAPPCISCOOBJS) \
$(CWACTION) \
$(MAVLOBJS) \
#include $(OBJS:.o=.d)
O:=$(OBJS);
OBJS:=$(patsubst %.o,$(ARCH)/%.o,$(OBJS))
CFLAGS = -Wall -g -O0 -D_REENTRANT -DWITH_IPV6 -DWITH_RMAC_SUPPORT -I /usr/local/include -I../
#CFLAGS = -Wall -Os -D_REENTRANT -DWITH_IPV6 -DWITH_RMAC_SUPPORT -I/usr/local/include
CFLAGS += $(GNUTLS_CFLAGS) \
-DWITH_CW_LOG \
-DWITH_CW_LOG_DEBUG \
-DWITH_DTLS \
$(XINCLUDE)\
-I $(OPENSSLINC)\
-Werror
#SRCS = $(OBJS:.o=.c)
#MODOBJS=$(wildcard ./mod/cipwap/$(ARCH)/*.o)
#MODOBJS+=$(wildcard ./mod/capwap/$(ARCH)/*.o)
$(ARCH)/%.o:%.c
@mkdir -p $(ARCH)
@echo " CC "$<
@$(CC) -c $(CFLAGS) $< -o $@
# @$(CC) -MM $(CFLAGS) $< > $*.d
$(LIBDIR)/$(NAME) : $(OBJS) $(MODOBJS)
@mkdir -p $(LIBDIR)
@echo " AR $(LIBDIR)/$(NAME)"
@$(AR) rcs $(LIBDIR)/$(NAME) $(OBJS) $(MODOBJS)
SRCS = $(OBJS:.o=.c)
DEPS := $(OBJS:.o=.d)
.PHONY: deps clean clean_libs libs
# top-level rule, to compile everything.
all: $(ARCH)/$(NAME)
clean:
$(RM) $(ARCH)/*
# $(RM) $(OBJS)
# $(RM) $(DEPS)
# $(RM) $(ARCH)/$(NAME)
clean_deps:
$(DEPS)
deps: $(SRCS)
$(CC) -MD -E $(SRCS) $(CFLAGS) >/dev/null
-include $(DEPS)

78
src/cw/acinfo_print.c Normal file
View File

@ -0,0 +1,78 @@
/**
* @file
* @breif defines acinfo_print function
*/
#include <string.h>
#include <stdio.h>
#include "capwap.h"
#include "sock.h"
#include "acinfo.h"
#include "cw_util.h"
/**
* Formats an acinfo object.
*
*/
int acinfo_print(char *str,const struct ac_info *acinfo)
{
char *s = str;
s+=sprintf(s,"\tAC name: %s\n",acinfo->ac_name);
s+=sprintf(s,"\tHardware version: ");
s+=cw_format_version(s,acinfo->hardware_version,0,"-");
s+=sprintf(s,"\n");
s+=sprintf(s,"\tSoftware version: ");
s+=cw_format_version(s,acinfo->software_version,0,"-");
s+=sprintf(s,"\n");
s+=sprintf(s,"\tStations: %i\n",acinfo->stations);
s+=sprintf(s,"\tSation limit: %i\n",acinfo->limit);
s+=sprintf(s,"\tActive WTPs: %i\n",acinfo->active_wtps);
s+=sprintf(s,"\tMax WTPs: %i\n",acinfo->max_wtps);
char help[64];
sock_addrtostr((struct sockaddr*)&acinfo->local_ip,help,64);
s+=sprintf(s,"\tLocal IP: %s\n",help);
s+=sprintf(s,"\tECN support: %s\n",acinfo->ecn_support==0 ? "limited" : "full");
s+=sprintf(s,"\tRMAC support: %s\n",acinfo->rmac==1 ? "supported" : "not supported");
help[0]=0;
if (acinfo->security & AC_SECURITY_S)
strcpy(help,"psk");
if (acinfo->security & AC_SECURITY_X){
if (strlen(help))
strcat(help,"/");
strcat(help,"X.509");
}
if (!strlen(help))
strcpy(help,"None");
s+=sprintf(s,"\tSecurity: %s\n",help);
help[0]=0;
/* if (acinfo->dtls_policy & AC_DTLS_POLICY_D){
strcpy(help,"dtls");
}
if (acinfo->dtls_policy & AC_DTLS_POLICY_C){
if(strlen(help))
strcat(help,"/");
strcat(help,"clear");
}
*/ if (!strlen(help))
strcpy(help,"Not set");
s+=sprintf(s,"\tDTLS policy: %s\n",help);
return s-str;
}

78
src/cw/aciplist.c Normal file
View File

@ -0,0 +1,78 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "aciplist.h"
#include "avltree.h"
#include "sock.h"
static int acip_cmp(const void *x1, const void *x2)
{
struct cw_acip *ip1 = (struct cw_acip *) x1;
struct cw_acip *ip2 = (struct cw_acip *) x2;
int r = ip1->wtp_count - ip2->wtp_count;
if (r!=0)
return r;
if (ip1->ip.ss_family != ip2->ip.ss_family) {
if (ip1->ip.ss_family == AF_INET)
return -1;
else
return 1;
}
if (ip1->ip.ss_family == AF_INET) {
struct sockaddr_in *s2 = (struct sockaddr_in *) &ip2->ip;
struct sockaddr_in *s1 = (struct sockaddr_in *) &ip1->ip;
return memcmp(&s1->sin_addr, &s2->sin_addr,
sock_addrlen((struct sockaddr *) s1));
}
if (ip1->ip.ss_family == AF_INET6) {
struct sockaddr_in6 *s2 = (struct sockaddr_in6 *) &ip2->ip;
struct sockaddr_in6 *s1 = (struct sockaddr_in6 *) &ip1->ip;
return memcmp(&s1->sin6_addr.s6_addr, &s2->sin6_addr.s6_addr,
sock_addrlen((struct sockaddr *) s1));
}
return -1;
}
static void acip_del(void *d)
{
free(d);
}
cw_aciplist_t cw_aciplist_create()
{
return avltree_create(acip_cmp, acip_del);
}

24
src/cw/aciplist.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef __ACIPLIST_H
#define __ACIPLIST_H
#include "mavl.h"
struct cw_acip{
struct sockaddr_storage ip;
uint32_t wtp_count;
};
typedef struct cw_acip cw_acip_t;
typedef struct mavl * cw_aciplist_t;
extern cw_aciplist_t cw_aciplist_create();
#define cw_aciplist_destroy(l) mavl_destroy(l)
#define cw_aciplist_add(l,elem) mavl_add(l,elem)
#define cw_aciplist_del(l,elem) mavl_del(l,elem)
#define cw_aciplist_foreach(l,callback,cbpriv) mavl_foreach_asc(l,callback,cbpriv)
#define cw_aciplist_replace(l,r) mavl_replace(l,r)
#endif

74
src/cw/acpriolist.c Normal file
View File

@ -0,0 +1,74 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "acpriolist.h"
static int acprio_cmp(const void *x1, const void *x2)
{
cw_acprio_t * p1 = (cw_acprio_t*)x1;
cw_acprio_t * p2 = (cw_acprio_t*)x2;
return strcmp (p1->name,p2->name);
}
static void acprio_del(void *d)
{
cw_acprio_t *p = (cw_acprio_t*)d;
if ( p->name )
free (p->name);
// if ( p->addr )
// free(p->addr);
free(d);
}
const struct mbag_typedef mbag_type_acprio = {
"acprio",acprio_del
};
cw_acpriolist_t cw_acpriolist_create()
{
return mavl_create(acprio_cmp, acprio_del);
}
cw_acprio_t * cw_acpriolist_add(cw_acpriolist_t l, const char *name,int name_len, uint8_t prio)
{
cw_acprio_t * s=malloc(sizeof(cw_acprio_t));
if (!s)
return 0;
s->name=strndup(name,name_len);
s->prio=prio;
cw_acpriolist_del(l,s);
return mavl_add(l,s);
}

39
src/cw/acpriolist.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef __ACIPRIORITYLIST_H
#define __ACIPRIORITYLIST_H
#include "mavl.h"
#include "mbag.h"
//#include "mavl.h"
struct cw_acprio{
char *name;
struct sockaddr_storage * addr;
uint8_t prio;
};
extern const struct mbag_typedef mbag_type_acprio;
#define MBAG_ACPRIO (&mbag_type_acprio)
typedef struct cw_acprio cw_acprio_t;
typedef struct mavl * cw_acpriolist_t;
extern cw_acpriolist_t cw_acpriolist_create();
cw_acprio_t * cw_acpriolist_add(cw_acpriolist_t l, const char *name,int name_len, uint8_t prio);
static inline int cw_acpriolist_get(cw_acpriolist_t l, char * acname){
cw_acprio_t ps,*pf;
ps.name=acname;
pf=mavl_get(l,&ps);
if (!pf)
return 256;
return pf->prio;
}
#define cw_acpriolist_del(l,s) mavl_del(l,s)
#define cw_acpriolist_set(l,n,nl,p) cw_acpriolist_add(l,n,nl,p)
#endif

359
src/cw/action.c Normal file
View File

@ -0,0 +1,359 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Implementation of methods for actionlists.
*/
#include <stdlib.h>
#include <string.h>
#include "action.h"
static inline int cw_action_in_cmp(const void *elem1, const void *elem2)
{
struct cw_action_in *e1 = (struct cw_action_in *) elem1;
struct cw_action_in *e2 = (struct cw_action_in *) elem2;
int r;
r = e1->capwap_state - e2->capwap_state;
if (r != 0)
return r;
r = e1->msg_id - e2->msg_id;
if (r != 0)
return r;
r = e1->elem_id - e2->elem_id;
if (r != 0)
return r;
r = e1->vendor_id - e2->vendor_id;
if (r != 0)
return r;
r = e1->proto - e2->proto;
if (r != 0)
return r;
return 0;
}
/*
cw_action_fun_t cw_set_msg_end_callback(struct conn *conn,
int capwap_state,int msg_id, cw_action_fun_t callback)
{
cw_action_in_t as;
as.capwap_state = capwap_state;
as.msg_id = msg_id;
as.vendor_id = 0;
as.elem_id = 0;
as.proto = 0;
cw_action_in_t *af;
af = cw_actionlist_in_get(conn->actions->in, &as);
if (!af)
return NULL;
cw_action_fun_t old = af->end;
af->end =callback;
return old;
}
*/
cw_action_in_t *cw_actionlist_in_add(cw_actionlist_in_t t, struct cw_action_in * a)
{
int s = sizeof(struct cw_action_in);
void *r = mavl_replace_data(t, a, s);
if (r)
return r;
void *an = malloc(s);
if (!an)
return NULL;
memcpy(an, a, s);
return mavl_add(t, an);
// return cw_actionlist_add(t, a, sizeof(struct cw_action_in));
}
struct cw_action_in *cw_actionlist_in_get(cw_actionlist_in_t t, struct cw_action_in *a)
{
return avltree_get(t, a);
}
/**
* Create an action list for incomming messages
*/
cw_actionlist_in_t cw_actionlist_in_create()
{
return mavl_create(cw_action_in_cmp, free);
}
/**
* Register actions in an action list for incommin messages
* @param t action list, where messaes will be registered
* @param actions an array of actions to reggister
*/
int cw_actionlist_in_register_actions(cw_actionlist_in_t t, cw_action_in_t * actions)
{
int n=0;
while (actions->capwap_state) {
cw_action_in_t *rc = cw_actionlist_in_add(t, actions);
if (!rc)
return 0;
actions++;
n++;
}
return n;
}
int cw_actionlist_out_register_actions(cw_actionlist_out_t t, cw_action_out_t * actions)
{
int n=0;
while (actions->msg_id != 0) {
cw_action_out_t *rc = cw_actionlist_out_add(t, actions);
if (rc == 0)
return 0;
actions++;
n++;
}
return n;
}
struct outelem{
uint32_t msg_id;
mlist_t * mlist;
};
/*
* Compare function for actionlist_out_t lists
*/
static int cw_action_out_cmp(const void *elem1, const void *elem2)
{
struct outelem *e1 = (struct outelem *) elem1;
struct outelem *e2 = (struct outelem *) elem2;
return e1->msg_id - e2->msg_id;
return 0;
}
static int mout_cmp(void *elem1,void *elem2)
{
struct cw_action_out *e1 = (struct cw_action_out *) elem1;
struct cw_action_out *e2 = (struct cw_action_out *) elem2;
int r;
r = e1->msg_id - e2->msg_id;
if (r )
return r;
r = e1->elem_id - e2->elem_id;
if (r )
return r;
r = e1->vendor_id - e2->vendor_id;
if (r )
return r;
if (e1->item_id == e1->item_id)
return 0;
if (e1->item_id && e2->item_id)
return strcmp(e1->item_id,e2->item_id);
return 1;
}
/**
* Add an action to an action
* @param t actionlist
* @param a action to add
* @param s size of element to add
* @return pointer to added element or NULL if an error has opccured
*/
void *cw_actionlist_add(struct avltree *t, void *a, size_t s)
{
void *r = mavl_replace_data(t, a, s); //sizeof(struct cw_action_in));
if (r) {
return r;
}
void *an = malloc(s);
if (!an)
return NULL;
memcpy(an, a, s);
return avltree_add(t, an);
}
#include "dbg.h" // Tube
/**
* Create an action list for outgoing message lements
* @return the created action list or NULL if an erro has occured.
*/
cw_actionlist_out_t cw_actionlist_out_create()
{
return mavl_create(cw_action_out_cmp, free);
}
static struct outelem * cw_actionlist_out_get_outelem(cw_actionlist_out_t t, int msg_id)
{
struct outelem search;
search.msg_id=msg_id;
//printf("Searching for %d\n",msg_id);
return mavl_get(t,&search);
}
mlist_t * cw_actionlist_out_get(cw_actionlist_out_t t,int msg_id)
{
struct outelem *o = cw_actionlist_out_get_outelem(t,msg_id);
if (!o)
return NULL;
return o->mlist;
}
struct outelem * cw_actionlist_mout_create(int msg_id)
{
struct outelem * o = malloc(sizeof(struct outelem));
if (!o)
return NULL;
o->mlist= mlist_create(mout_cmp);
if (!o->mlist){
free(o);
return NULL;
}
o->msg_id=msg_id;
return o;
}
#include "capwap.h"
cw_action_out_t *cw_actionlist_out_add(cw_actionlist_out_t t, struct cw_action_out * a)
{
/* if (a->msg_id==CW_MSG_DISCOVERY_RESPONSE){
printf("Add discovery response\n");
}
*/
struct outelem * o = cw_actionlist_out_get_outelem(t,a->msg_id);
if (!o){
/* if (a->msg_id==CW_MSG_DISCOVERY_RESPONSE){
printf("m was 0 creating \n");
}
*/
o = cw_actionlist_mout_create(a->msg_id);
if (!o) {
return NULL;
}
mavl_add(t,o);
}
struct mlist_elem * e = mlist_replace(o->mlist,NULL,a);
if (!e)
e = mlist_append(o->mlist,a);
if (e)
return a;
return 0;
}
/*
cw_action_in_t *cw_actionlist_in_set_msg_end_callback(cw_actionlist_in_t a,
uint8_t capwap_state,
uint32_t msg_id,
int (*fun) (struct conn * conn,
struct cw_action_in * a, uint8_t * data,
int len,struct sockaddr *from))
{
cw_action_in_t as,*ar;
as.vendor_id=0;
as.proto=0;
as.elem_id=-1;
as.msg_id=msg_id;
as.capwap_state=capwap_state;
ar = cw_actionlist_in_get(a,&as);
if (!ar)
return NULL;
ar->end=fun;
return ar;
}
*/

184
src/cw/action.h Normal file
View File

@ -0,0 +1,184 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief CAPWAP ACtions Header
* @defgroup ACTION CAPWAP/LWAPP Actions
* @{
*/
#ifndef __ACTION_H
#define __ACTION_H
#include <stdint.h>
#include "mavl.h"
#include "conn.h"
#include "mbag.h"
#include "strheap.h"
#include "intavltree.h"
#include "item.h"
#include "mlist.h"
struct conn;
/**
* @file action.h
* @brief Header for actions
*/
/**
* @defgroup ACTION Action
* @{
*/
/**
* Definition of an action for incomming messages
*/
struct cw_action_in{
uint32_t vendor_id;
uint8_t proto;
uint8_t capwap_state;
uint32_t msg_id;
uint16_t elem_id;
int (*start)(struct conn *conn,struct cw_action_in *a,uint8_t*data,int len,struct sockaddr *from);
int (*end)(struct conn *conn,struct cw_action_in *a,uint8_t*elem,int len,struct sockaddr *from);
const struct mbag_typedef * itemtype;
const char * item_id;
uint16_t min_len;
uint16_t max_len;
uint8_t mand;
};
/** a handy type for incomming actions */
typedef struct cw_action_in cw_action_in_t;
/** Definition of an action list for incomming messages */
typedef mavl_t cw_actionlist_in_t;
extern cw_actionlist_in_t cw_actionlist_in_create();
extern cw_action_in_t * cw_actionlist_in_get(cw_actionlist_in_t t,cw_action_in_t *a);
//extern cw_action_in_t * cw_actionlist_in_add(cw_actionlist_in_t t,cw_action_in_t *a);
extern int cw_actionlist_in_register_actions(cw_actionlist_in_t t,cw_action_in_t * actions);
/**
* Definitioni of an action foroutgoing messages
* */
struct cw_action_out{
uint32_t msg_id;
const char * item_id;
uint32_t vendor_id;
uint16_t elem_id;
int (*init)(struct conn * conn, struct cw_action_out *a, uint8_t * dst);
int (*out)(struct conn * conn, struct cw_action_out *a, uint8_t * dst);
struct mbag_item *(*get)(struct conn *conn,struct cw_action_out *a);
uint8_t mand;
struct mbag_typedef * itemtype;
void *defval;
};
typedef struct cw_action_out cw_action_out_t;
typedef struct mavl *cw_actionlist_out_t;
extern cw_actionlist_out_t cw_actionlist_out_create();
extern int cw_actionlist_out_register_actions(cw_actionlist_out_t t,cw_action_out_t * actions);
mlist_t * cw_actionlist_out_get(cw_actionlist_out_t,int msg_id);
//extern cw_action_out_t * cw_actionlist_out_add(cw_actionlist_out_t t, struct cw_action_out * a);
/**
* @}
*/
extern cw_actionlist_out_t cw_actionlist_out_create();
extern cw_action_out_t * cw_actionlist_out_add(cw_actionlist_out_t t, struct cw_action_out * a);
extern int cw_actionlist_out_register_actions(cw_actionlist_out_t t,cw_action_out_t * actions);
/**
* Definition CAPWAP modes
*/
enum capwapmodes {
/** Auto -- means auto detect the CAPWAP mode and
it set as soon as possible */
CW_MODE_AUTO,
/** Standard CAPWAP mode as specified in RFC 5415 */
CW_MODE_CAPWAP,
/** Cisco specific CAPWAP */
CW_MODE_CISCO,
/** CIPWAP, a mix of standard CAPWAP and some
Cisco extension */
CW_MODE_CIPWAP,
/** Zyxel */
CW_MODE_ZYXEL,
/** Lancom */
CW_MODE_LANCOM,
/** Fortinet */
CW_MODE_FORTINET
};
struct cw_actiondef{
cw_actionlist_in_t in;
cw_actionlist_out_t out;
cw_strheap_t strmsg;
cw_strheap_t strelem;
cw_itemdefheap_t items;
cw_itemdefheap_t radioitems;
mlist_t * mout;
/** Supported Wireless Binding IDs (WBID) */
struct avltree * wbids;
};
extern struct outelem * cw_actionlist_out_get_mlist(cw_actionlist_out_t t, int msg_id);
#define cw_actionlist_get_node(t,a) avltree_get_node(t,a)
/**@}*/
#endif

69
src/cw/avliter_next.c Normal file
View File

@ -0,0 +1,69 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
*@file
*@brief Implementation of avliter_next
*/
#include "avltree.h"
/**
* Get the next element within an AVL Tree.
* @param i pointer to AVL Iterator
* @return the element or NULL if there is no next elemeent.
*/
void * avliter_next(avliter_t *i)
{
while ( i->stack_ptr) {
i->stack_ptr--;
i->cur=i->stack[i->stack_ptr];
if (!i->cur)
continue;
if ((i->stack_ptr)&1) {
return i->cur->data;
}
break;
}
if (!i->cur){
return NULL;
}
while(i->cur->left) {
/* push right branch */
i->stack[i->stack_ptr++]=i->cur->right;
/* push node */
i->stack[i->stack_ptr++]=i->cur;
i->cur=i->cur->left;
}
i->stack[i->stack_ptr++]=i->cur->right;
return i->cur->data;
}

66
src/cw/avliter_seek.c Normal file
View File

@ -0,0 +1,66 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
*@file
*@brief Implementation of avliter_seek
*/
#include "avltree.h"
/**
* Set an AVL Iterator to a specific position.
* @param i AVL Iterator
* @param d element to search for
* @return element found or NULL if not found
*/
void * avliter_seek(avliter_t *i,void *d)
{
if (!i->root)
return NULL;
i->cur=i->root;
i->stack_ptr=0;
int rc;
while(i->cur) {
rc = i->cmp(d,i->cur->data);
if (rc==0){
i->stack[i->stack_ptr++]=i->cur->right;
i->stack[i->stack_ptr++]=i->cur;
return avliter_next(i);
}
if (rc<0) {
i->stack[i->stack_ptr++]=i->cur->right;
i->stack[i->stack_ptr++]=i->cur;
i->cur=i->cur->left;
}
if (rc>0) {
i->cur=i->cur->right;
}
}
return NULL;
}

45
src/cw/avltree.h Normal file
View File

@ -0,0 +1,45 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef __AVLTREE_H
#define __AVLTREE_H
#include "mavl.h"
#define avltree mavl
#define avltree_get mavl_get
#define avltree_destroy mavl_destroy
#define avltree_create mavl_create
#define avltree_add mavl_add
#define avltree_del mavl_del
#define avltree_replace mavl_replace
#define avliter_foreach_from mavliter_foreach_from
#define avliter_foreach mavliter_foreach
#define avltree_foreach_asc mavl_foreach_asc
#define avliter_get mavliter_get
#define avltree_replace_data mavl_replace_data
#define avliter_seek mavliter_seek
#define avliter_seek_set mavliter_seek_set
#define avliter_next mavliter_next
#define avltree_del_all mavl_del_all
#define DEFINE_AVLITER MAVLITER_DEFINE
#endif

36
src/cw/avltree_del_all.c Normal file
View File

@ -0,0 +1,36 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "avltree.h"
static void avltree_del_all0(struct avltree *t ,struct avlnode * n)
{
if (!n)
return;
avltree_del_all0(t,n->left);
avltree_del_all0(t,n->right);
avlnode_destroy(t,n);
}
void avltree_del_all(struct avltree *t)
{
avltree_del_all0(t,t->root);
t->root=0;
}

39
src/cw/avltree_foreach.c Normal file
View File

@ -0,0 +1,39 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "avltree.h"
int avltree_foreach_rl(struct avlnode *n, int (*callback)(void *,void *),void *cbpriv)
{
if (!n)
return 1;
if (!avltree_foreach_rl(n->right,callback,cbpriv))
return 0;
if (!callback(cbpriv,n->data))
return 0;
return avltree_foreach_rl(n->left,callback,cbpriv);
}
void avltree_foreach(struct avltree *t, int (*callback)(void *,void *),void * cbpriv,int dir)
{
if (dir)
avltree_foreach_lr(t->root,callback,cbpriv);
else
avltree_foreach_rl(t->root,callback,cbpriv);
}

View File

@ -0,0 +1,31 @@
#include "avltree.h"
// XXX Function is buggy
int avltree_foreach_from_lr(struct avltree *t, struct avlnode *n, void *data,int (*callback)(void *,void *),void *cbpriv)
{
if (!n)
return 1;
int rc=t->cmp(data,n->data);
if (rc<0){
if(!avltree_foreach_from_lr(t,n->left,data,callback,cbpriv))
return 0;
if (!callback(cbpriv,n->data))
return 0;
return avltree_foreach_lr(n->right,callback,cbpriv);
}
if (rc>0) {
avltree_foreach_from_lr(t,n->right,data,callback,cbpriv);
return 0;
}
if (!callback(cbpriv,n->data))
return 0;
return avltree_foreach_lr(n->right,callback,cbpriv);
}

View File

@ -0,0 +1,17 @@
#include "avltree.h"
int avltree_foreach_lr(struct avlnode *n, int (*callback)(void *,void *),void *cbpriv)
{
if (!n)
return 1;
if (!avltree_foreach_lr(n->left,callback,cbpriv))
return 0;
if (!callback(cbpriv,n->data))
return 0;
return avltree_foreach_lr(n->right,callback,cbpriv);
}

View File

@ -0,0 +1,33 @@
int avltree_foreach_lr_node(struct avltree *t, struct avlnode *n, void *data,int (*callback)(void *,void *),void *cbpriv)
{
if (!n)
return 1;
int rc=t->cmp(data,n->data);
if (rc<0){
avltree_foreach_lr_node(t,n->left,data,callback,cbpriv);
callback(cbpriv,n->data);
avltree_foreach_lr(n->right,
return 0;
}
if (rc>0) {
avltree_foreach_lr_node(t,n->right,data,callback,cbpriv);
return 0;
}
return callback(cbpriv,n->data);
}
int avltree_foreach_2(struct avltree *t,void *data,int (*callback)(void *,void *),void *cbpriv)
{
}

View File

@ -0,0 +1,18 @@
#include "avltree.h"
int avltree_foreach_rl(struct avlnode *n, int (*callback)(void *,void *),void *cbpriv)
{
if (!n)
return 1;
if (!avltree_foreach_rl(n->right,callback,cbpriv))
return 0;
if (!callback(cbpriv,n->data))
return 0;
return avltree_foreach_rl(n->left,callback,cbpriv);
}

47
src/cw/avltree_get.c Normal file
View File

@ -0,0 +1,47 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Implementation of avltree_get
*/
#include <stdio.h>
#include "avltree.h"
/**
* Get an AVL tree element.
* @param data Element to get
* @return pointer to element or NULL if not found.
*/
void * avltree_get(struct avltree *t ,void *data)
{
struct avlnode *n = t->root;
while(n){
int rc=t->cmp(data,n->data);
if (rc==0)
return n->data;
if (rc<0)
n=n->left;
else
n=n->right;
}
return NULL;
}

39
src/cw/avltree_get_node.c Normal file
View File

@ -0,0 +1,39 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "avltree.h"
struct avlnode * avltree_get_node(struct avltree *t ,void *data)
{
struct avlnode *n = t->root;
while(n){
int rc=t->cmp(data,n->data);
if (rc==0)
return n;
if (rc<0)
n=n->left;
else
n=n->right;
}
return NULL;
}

172
src/cw/bstr.h Normal file
View File

@ -0,0 +1,172 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Definitions for bstr functions
* @defgroup Bstr BSTR
* @brief BSTR is used to store binary strings.
* We can see them anywhere.
* @{
*/
#ifndef __BSTR_H
#define __BSTR_H
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
/**
* bstr type
*
* bstr_t serves as binary string where the first byte contains
* the length of the string.
*/
typedef uint8_t* bstr_t;
extern uint8_t * bstr_create(uint8_t *data, uint8_t len);
extern uint8_t * bstr_create_from_cfgstr(const char * s);
extern uint8_t * bstr_replace( bstr_t * dst, uint8_t * bstr);
extern int bstr_to_str(char *dst, bstr_t str,char * def);
/**
* Return the length of a bstr_t string.
*/
#define bstr_len(s) (*((uint8_t*)(s)))
/**
* Return the data of a bstr_t string.
*/
#define bstr_data(s) ((s)+1)
/**
* Return the actual size in memory a bstr_t string needs.
*/
#define bstr_size(len) (len+1)
/**
*@defgroup BstrConstants Types & Constants
*@{
*/
/**
* Maximum length of a bstr_t string.
*/
#define BSTR_MAX_LEN 254
/**
* The same as #bstr_t, but there are two bytes used
* to describe the length of the string.
*/
typedef uint8_t *bstr16_t;
/**@}*/
/**
* Return the length of a bstr16_t string.
*/
#define bstr16_len(s) ( *((uint16_t*)(s)) )
/**
* Return a pointer to the data of a bstr16_t string.
*/
#define bstr16_data(s) (((uint8_t*)s)+2)
/**
* Return the actual size of a bstr16_t string. That's the
* this objects needs in memory to be stored.
*/
#define bstr16_size(l) (l+2)
/**
Maximum length of a #bstr16_t string
*/
#define BSTR16_MAX_LEN (0xffff-2)
/*
static inline int bstr16_ncpy(uint8_t *dst,uint8_t*src,uint16_t len)
{
*((uint16_t*)dst)=len;
memcpy(dst+2,src,len);
return len+2;
}
*/
static inline uint8_t * bstr16_create(uint8_t *data, uint16_t len)
{
uint8_t * str = malloc(2+len*sizeof(uint8_t));
if (!str)
return 0;
*((uint16_t*)str)=len;
memcpy(str+2,data,len);
return str;
}
uint8_t * bstr16_create_from_str(const char *s);
typedef uint8_t * vendorstr_t;
#define vendorstr_get_vendor_id(str)\
( *((uint32_t*)((str)+2)))
#define vendorstr_set_vendor_id(str,id)\
( *((uint32_t*)((str)+2)) = id)
#define vendorstr_len(str)\
(*((uint16_t*)((str)+0)))
#define vendorstr_set_len(str,len)\
(*((uint16_t*)((str)+0))=len)
#define vendorstr_data(str)\
(((uint8_t*)(str))+6)
#define vendorstr_size(n)\
(1+6+(n)*sizeof(uint8_t))
static inline uint8_t * vendorstr_create(uint32_t vendor_id, uint8_t *data, uint8_t len)
{
uint8_t * str = malloc(vendorstr_size(len));
if (!str)
return 0;
vendorstr_set_vendor_id(str,vendor_id);
vendorstr_set_len(str,len);
memcpy(vendorstr_data(str),data,len);
*(vendorstr_data(str)+vendorstr_len(str))=0;
return str;
}
uint8_t * vendorstr_create_from_str(uint32_t vendor_id,const char *s);
uint8_t * bstr16cfgstr(const char * s);
#endif
/**@}*/

View File

@ -0,0 +1,30 @@
#include "bstr.h"
#include "format.h"
uint8_t * bstr16_create_from_str(const char *s)
{
int l = strlen(s);
if (s[0]!='.')
return bstr16_create((uint8_t*)s,l);
if (l<=2)
return bstr16_create((uint8_t*)s,l);
if (s[1]=='.')
return bstr16_create((uint8_t*)s+1,l-1);
if (s[1]!='x')
return bstr16_create((uint8_t*)s,l);
/* the string starts with ".x" - read hexbytes */
l-=2;
int msize=l/2;
if(l&1)
msize++;
uint8_t * mem = malloc(2+msize);
*((uint16_t*)mem)=msize;
cw_format_scan_hex_bytes(mem+2,s+2,l);
return mem;
}

67
src/cw/bstr16cfgstr.c Normal file
View File

@ -0,0 +1,67 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "bstr.h"
/**
* Create a bstr1616_t string from a string read from config file.
*
* @param s String from config file.
* @return The create bstr16_t string.
*
* The string from config file is an ASCII-text which is interpreted
* as hexadecimal string if it starts with ".x"
*
* @see bstr16_t
*/
uint8_t * bstr16cfgstr(const char * s)
{
int l = strlen(s);
if (s[0]!='.')
return bstr16_create((uint8_t*)s,l);
if (l<=2)
return bstr16_create((uint8_t*)s,l);
if (s[1]=='.')
return bstr16_create((uint8_t*)s+1,l-1);
if (s[1]=='x'){
uint8_t * ns=0;
int len=0;
int ch,cl;
const char *ss = s+2;
int rc ;
do {
rc = sscanf(ss,"%01X",&ch);
if (rc!=1)
break;
ss++;
rc = sscanf(ss,"%01X",&cl);
if (rc!=1)
cl=0;
ss++;
int c=(ch<<4) | cl;
len++;
ns = realloc(ns,len);
ns[len-1]=c;
}while (rc==1);
return bstr16_create(ns,len);
}
return NULL;
}

45
src/cw/bstr_create.c Normal file
View File

@ -0,0 +1,45 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief
*/
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
/**
* Creates a bstr_t string.
* @param data source data to create the string from
* @param len length of the string
* @return the created bstr_t string.
*
* The bstr_t string returned is allocated by malloc. So remember to free
* this resource if you don't need it anymore.
*/
uint8_t * bstr_create(uint8_t *data, uint8_t len)
{
uint8_t * str = malloc(1+len*sizeof(uint8_t));
if (!str)
return 0;
*str=len;
memcpy(str+1,data,len);
return str;
}

View File

@ -0,0 +1,90 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief bstr_create_from_cfgstr function
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "bstr.h"
/**
* Create a bstr_t string from a string read from config file.
*
* @param s String from config file.
* @return The create bstr_t string.
*
* The string from config file is an ASCII-text which is interpreted
* as hexadecimal string if it starts with ".x"
*
* @see bstr_t
*/
uint8_t * bstr_create_from_cfgstr(const char * s)
{
int l = strlen(s);
if (s[0]!='.')
return bstr_create((uint8_t*)s,l);
if (l<=2)
return bstr_create((uint8_t*)s,l);
if (s[1]=='.')
return bstr_create((uint8_t*)s+1,l-1);
if (s[1]=='x'){
uint8_t * ns=0;
int len=0;
int ch,cl;
const char *ss = s+2;
int rc ;
do {
rc = sscanf(ss,"%01X",&ch);
if (rc!=1)
break;
ss++;
rc = sscanf(ss,"%01X",&cl);
if (rc!=1)
cl=0;
ss++;
int c=(ch<<4) | cl;
len++;
ns = realloc(ns,len);
ns[len-1]=c;
}while (rc==1);
return bstr_create(ns,len);
}
return NULL;
}

View File

@ -0,0 +1,31 @@
#include "bstr.h"
#include "format.h"
uint8_t * bstr_create_from_str(const char *s)
{
int l = strlen(s);
if (s[0]!='.')
return bstr_create((uint8_t*)s,l);
if (l<=2)
return bstr_create((uint8_t*)s,l);
if (s[1]=='.')
return bstr_create((uint8_t*)s+1,l-1);
if (s[1]!='x')
return bstr_create((uint8_t*)s,l);
/* the string starts with ".x" - read hexbytes */
l-=2;
int msize=l/2;
if(l&1)
msize++;
uint8_t * mem = malloc(1+msize);
*((uint8_t*)mem)=msize;
cw_format_scan_hex_bytes(mem+2,s+2,l);
return mem;
}

12
src/cw/bstr_replace.c Normal file
View File

@ -0,0 +1,12 @@
#include <stdlib.h>
#include "bstr.h"
uint8_t * bstr_replace( bstr_t * dst, uint8_t * bstr)
{
if (*dst)
free(*dst);
*dst = bstr;
return *dst;
}

38
src/cw/bstr_to_str.c Normal file
View File

@ -0,0 +1,38 @@
#include <stdio.h>
#include <string.h>
#include "bstr.h"
#include "cw_util.h"
int bstr_to_str(char *dst, bstr_t str,char * def)
{
if (!str){
if (!def)
return 0;
return sprintf(dst,"%s",def);
}
int printable = cw_is_printable(bstr_data(str),bstr_len(str));
int l=bstr_len(str);
if (printable){
memcpy((char*)dst,bstr_data(str),l);
*(dst+l)=0;
return l;
}
int i;
int c=0;
char *s = dst;
for (i=0; i<l; i++){
if (!c){
s += sprintf(s,"%02X",bstr_data(str)[i]);
c=1;
}
else
s += sprintf(s,",%02X",bstr_data(str)[i]);
}
return s-dst;
}

1169
src/cw/capwap.h Normal file

File diff suppressed because it is too large Load Diff

102
src/cw/capwap_80211.h Normal file
View File

@ -0,0 +1,102 @@
#ifndef __CAPWAP_80211
#define __CAPWAP_80211
#include "capwap.h"
#include <stdint.h>
#include "bstr.h"
#include "action.h"
#define CW80211IANA_ENTERPRISE_NUMBER 13277
#define CWMSG_80211_WLAN_CONFIGURATION_REQUEST 3398913
#define CWMSG_80211_WLAN_CONFIGURATION_REPONSE 3398914
/** 802.11 Message Elements */
enum radioelems {
/** Add WLAN Message element */
CW_ELEM80211_ADD_WLAN =1024,
/** Antenna Message element */
CW_ELEM80211_ANTENNA =1025,
/*
IEEE 802.11 Assigned WTP BSSID 1026
IEEE 802.11 Delete WLAN 1027
IEEE 802.11 Direct Sequence Control 1028
IEEE 802.11 Information Element 1029
IEEE 802.11 MAC Operation 1030
IEEE 802.11 MIC Countermeasures 1031
IEEE 802.11 Multi-Domain Capability 1032
IEEE 802.11 OFDM Control 1033
*/
/** Supported WLAN Rates */
CW_ELEM80211_RATE_SET=1034,
/* IEEE 802.11 RSNA Error Report From Station 1035
IEEE 802.11 Station 1036
IEEE 802.11 Station QoS Profile 1037
IEEE 802.11 Station Session Key 1038
IEEE 802.11 Statistics 1039
IEEE 802.11 Supported Rates 1040
IEEE 802.11 Tx Power 1041
IEEE 802.11 Tx Power Level 1042
IEEE 802.11 Update Station QoS 1043
IEEE 802.11 Update WLAN 1044
IEEE 802.11 WTP Quality of Service 1045
IEEE 802.11 WTP Radio Configuration 1046
IEEE 802.11 WTP Radio Fail Alarm Indication 1047
*/
/** Radio Information Message Element */
CW_ELEM80211_WTP_RADIO_INFORMATION=1048
};
/*
* Messages
*/
#define CW_80211_RADIO_TYPE_B (1)
#define CW_80211_RADIO_TYPE_A (2)
#define CW_80211_RADIO_TYPE_G (4)
#define CW_80211_RADIO_TYPE_N (8)
struct cw_wlan {
uint8_t rid; /* Radio ID */
uint8_t wid; /* WLAN ID */
uint16_t capab;
uint8_t key_index;
uint8_t key_status;
uint16_t key_length;
uint8_t * key;
uint8_t group_tsc[6];
uint8_t qos;
uint8_t auth_type;
uint8_t mac_mode;
uint8_t tunnel_mode;
uint8_t suppress_ssid;
bstr_t ssid;
};
int cw_out_radio_infos(struct conn *conn, struct cw_action_out *a, uint8_t * dst);
extern int cw_register_actions_capwap_80211_wtp(struct cw_actiondef *def);
extern struct cw_strlist_elem capwap_strings_elem80211[];
extern int cw_register_actions_capwap_80211_ac(struct cw_actiondef *def);
#endif

View File

@ -0,0 +1,13 @@
#include "capwap_80211.h"
#include "capwap_items.h"
#define CW_ACTION_IN_80211_WTP_RADIO_INFORMATION \
CW_ELEM80211_WTP_RADIO_INFORMATION, /* Element ID*/ \
cw_in_radio_generic, 0, /* start/end callback */ \
MBAG_DWORD, /* Type of element */ \
CW_ITEM_LOCATION_DATA, /* ID to use store */ \
5, 5 /* min/max length */

View File

@ -0,0 +1,65 @@
#include "action.h"
#include "capwap_80211_actions.h"
#include "capwap_80211.h"
#include "capwap.h"
cw_action_in_t capwap_80211_actions_ac_in[] = {
/* --------------------------------------------------------
* Discovery Resquest
*/
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_REQUEST,
CW_ACTION_IN_80211_WTP_RADIO_INFORMATION, 1}
,
/* --------------------------------------------------------
* Discovery Resquest
*/
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST,
CW_ACTION_IN_80211_WTP_RADIO_INFORMATION, 1}
,
{0, 0, 0}
};
cw_action_out_t capwap_80211_actions_ac_out[]={
/* Radio Infos */
{CW_MSG_DISCOVERY_RESPONSE, NULL /*CW_ELEM80211_WTP_RADIO_INFORMATION*/, 0,
CW_ELEM80211_WTP_RADIO_INFORMATION, NULL,cw_out_radio_infos, NULL,1}
,
/* Radio Infos */
{CW_MSG_JOIN_RESPONSE, NULL /*CW_ELEM80211_WTP_RADIO_INFORMATION*/, 0,
CW_ELEM80211_WTP_RADIO_INFORMATION, NULL,cw_out_radio_infos, NULL,1}
,
{0,0,0}
};
int cw_register_actions_capwap_80211_ac(struct cw_actiondef *def)
{
int rc;
rc=cw_actionlist_in_register_actions(def->in, capwap_80211_actions_ac_in);
rc+=cw_actionlist_out_register_actions(def->out, capwap_80211_actions_ac_out);
rc+= cw_strheap_register_strings(def->strelem, capwap_strings_elem80211);
/*rc += cw_strheap_register_strings(def->strelem, capwap_strings_elem);
*/
return rc;
}

View File

@ -0,0 +1,64 @@
#include "action.h"
#include "capwap_80211_actions.h"
#include "capwap_80211.h"
#include "capwap.h"
cw_action_in_t capwap_80211_actions_wtp_in[] = {
/* Discovery Response */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_RESPONSE,
CW_ACTION_IN_80211_WTP_RADIO_INFORMATION, 1}
,
/* Join Response */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_RESPONSE,
CW_ACTION_IN_80211_WTP_RADIO_INFORMATION, 1}
,
{0, 0, 0}
};
cw_action_out_t capwap_80211_actions_wtp_out[]={
/* --------------------------------------------------------
* Discovery Resquest
*/
/* 802.11 Radio Information */
{CW_MSG_DISCOVERY_REQUEST, CW_ITEM_RADIO_INFOS /*CW_ELEM80211_WTP_RADIO_INFORMATION*/, 0,
CW_ELEM80211_WTP_RADIO_INFORMATION, NULL,cw_out_radio_infos, NULL,1}
,
/* --------------------------------------------------------
* Join Resquest
*/
/* 802.11 Radio Information */
{CW_MSG_JOIN_REQUEST, CW_ITEM_RADIO_INFOS, 0,
CW_ELEM80211_WTP_RADIO_INFORMATION, NULL,cw_out_radio_infos, NULL,1},
{0,0,0}
};
int cw_register_actions_capwap_80211_wtp(struct cw_actiondef *def)
{
int rc;
rc=cw_actionlist_in_register_actions(def->in, capwap_80211_actions_wtp_in);
rc+=cw_actionlist_out_register_actions(def->out, capwap_80211_actions_wtp_out);
rc+=cw_strheap_register_strings(def->strelem, capwap_strings_elem80211);
return rc;
}

View File

@ -0,0 +1,60 @@
#include "action.h"
#include "capwap.h"
int cw_in_set_state_none(struct conn *conn,struct cw_action_in * a,uint8_t *data,int len)
{
conn->capwap_state=CW_STATE_NONE;
return 1;
}
struct mbag_item *cw_out_get_outgoing(struct conn *conn, struct cw_action_out *a)
{
return mbag_get(conn->outgoing, a->item_id);
}
struct mbag_item *cw_out_get_incomming(struct conn *conn, struct cw_action_out *a)
{
return mbag_get(conn->incomming, a->item_id);
}
struct mbag_item *cw_out_get_local(struct conn *conn, struct cw_action_out *a)
{
return mbag_get(conn->local,a->item_id);
}
struct mbag_item *cw_out_get_config(struct conn *conn, struct cw_action_out *a)
{
return mbag_get(conn->config,a->item_id);
}
#include "capwap.h"
#include "capwap_items.h"
#include "log.h"
#include "rand.h"
struct mbag_item * cw_out_get_session_id(struct conn *conn,struct cw_action_out * a)
{
uint8_t session_id[16];
int slen;
if ( conn->capwap_mode == CW_MODE_CISCO){
slen=2;
}
else
slen=16;
int l = cw_rand(session_id,slen);
if ( l!=slen ) {
cw_log(LOG_ERR,"Can't init session ID.");
return NULL;
}
return mbag_set_bstrn(conn->local,CW_ITEM_SESSION_ID,session_id,slen);
}

196
src/cw/capwap_actions.h Normal file
View File

@ -0,0 +1,196 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef __CAPWAP_ACTIONS_H
#define __CAPWAP_ACTIONS_H
#include "capwap.h"
#include "capwap_items.h"
#define CW_ACTION_IN_LOCATION_DATA \
CW_ELEM_LOCATION_DATA, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_STR, /* Type of element */ \
CW_ITEM_LOCATION_DATA, /* ID to use store */ \
1, 1024 /* min/max length */
#define CW_ACTION_IN_WTP_NAME \
CW_ELEM_WTP_NAME, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_STR, /* Type of element */ \
CW_ITEM_WTP_NAME, /* ID to use store */ \
1, 1024 /* min/max length */
#define CW_ACTION_IN_SESSION_ID \
CW_ELEM_SESSION_ID, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_BSTR, /* Type of element */ \
CW_ITEM_SESSION_ID, /* ID to use store */ \
16, 16 /* min/max length */
#define CW_ACTION_IN_IMAGE_IDENTIFIER \
CW_ELEM_IMAGE_IDENTIFIER, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_VENDORSTR, /* Type of element */ \
CW_ITEM_IMAGE_IDENTIFIER, /* ID to use store */ \
5, 4096 /* min/max length */
#define CW_ACTION_IN_AC_NAME \
CW_ELEM_AC_NAME, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_STR, /* Type of element */ \
CW_ITEM_AC_NAME, /* ID to use store */ \
1, 512 /* min/max length */
#define CW_ACTION_IN_STATISTICS_TIMER \
CW_ELEM_STATISTICS_TIMER, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_WORD, /* Type of element */ \
CW_ITEM_STATISTICS_TIMER, /* ID to use store */ \
2, 2 /* min/max length */
#define CW_ACTION_IN_WTP_REBOOT_STATISTICS \
CW_ELEM_WTP_REBOOT_STATISTICS, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_DATA, /* Type of element */ \
CW_ITEM_WTP_REBOOT_STATISTICS, /* ID to use store */ \
15, 15 /* min/max length */
#define CW_ACTION_IN_WTP_FRAME_TUNNEL_MODE \
CW_ELEM_WTP_FRAME_TUNNEL_MODE, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_BYTE, /* Type of element */ \
CW_ITEM_WTP_FRAME_TUNNEL_MODE, /* ID to use store */ \
1, 1 /* min/max length */
#define CW_ACTION_IN_WTP_MAC_TYPE \
CW_ELEM_WTP_MAC_TYPE, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_BYTE, /* Type of element */ \
CW_ITEM_WTP_MAC_TYPE, /* ID to use store */ \
1, 1 /* min/max length */
#define CW_ACTION_IN_VENDOR_SPECIFIC_PAYLOAD \
CW_ELEM_VENDOR_SPECIFIC_PAYLOAD, /* Element ID */ \
cw_in_vendor_specific_payload,0, /* start/end callback*/ \
0, \
0, \
0,0
#define CW_ACTION_IN_WTP_BOARD_DATA \
CW_ELEM_WTP_BOARD_DATA, /* Element ID */ \
cw_in_wtp_board_data, 0, /* start/end callback */ \
0, \
CW_ITEM_WTP_BOARD_DATA, \
0,0
#define CW_ACTION_IN_WTP_DESCRIPTOR \
CW_ELEM_WTP_DESCRIPTOR, /* Element ID */ \
cw_in_wtp_descriptor, 0, /* start/end callback */ \
0, \
CW_ITEM_WTP_DESCRIPTOR, \
0,0
#define CW_ACTION_IN_CAPWAP_CONTROL_IPV4_ADDRESS \
CW_ELEM_CAPWAP_CONTROL_IPV4_ADDRESS, /* Element ID*/ \
cw_in_capwap_control_ipv4_address, 0, /* start/end callback */ \
MBAG_AVLTREE, /* Type of element */ \
CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST, /* ID to use store */ \
6, 6 /* min/max length */
#define CW_ACTION_IN_CAPWAP_CONTROL_IPV6_ADDRESS \
CW_ELEM_CAPWAP_CONTROL_IPV6_ADDRESS, /* Element ID*/ \
cw_in_capwap_control_ipv4_address, 0, /* start/end callback */ \
MBAG_AVLTREE, /* Type of element */ \
CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST, /* ID to use store */ \
18,18 /* min/max length */
#define CW_ACTION_IN_AC_DESCRIPTOR \
CW_ELEM_AC_DESCRIPTOR, /* Element ID*/ \
cw_in_ac_descriptor, 0, /* start/end callback */ \
MBAG_DATA, /* Type of element */ \
CW_ITEM_AC_DESCRIPTOR, /* ID to use store */ \
12, 8192 /* min/max length */
#define CW_ACTION_IN_RESULT_CODE \
CW_ELEM_RESULT_CODE, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_DWORD, /* Type of element */ \
CW_ITEM_RESULT_CODE, /* ID to use store */ \
4, 4 /* min/max length */
#define CW_ACTION_IN_CAPWAP_TIMERS \
CW_ELEM_CAPWAP_TIMERS, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_WORD, /* Type of element */ \
CW_ITEM_CAPWAP_TIMERS, /* ID to use store */ \
2, 2 /* min/max length */
#define CW_ACTION_IN_IDLE_TIMEOUT \
CW_ELEM_IDLE_TIMEOUT, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_DWORD, /* Type of element */ \
CW_ITEM_IDLE_TIMEOUT, /* ID to use store */ \
4, 4 /* min/max length */
#define CW_ACTION_IN_AC_NAME_WITH_PRIORITY \
CW_ELEM_IDLE_TIMEOUT, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_DWORD, /* Type of element */ \
CW_ITEM_IDLE_TIMEOUT, /* ID to use store */ \
4, 4 /* min/max length */
#define CW_ACTION_IN_RADIO_ADMINISTRATIVE_STATE \
CW_ELEM_RADIO_ADMINISTRATIVE_STATE, /* Element ID*/ \
cw_in_radio_administrative_state, 0, /* start/end callback */ \
MBAG_DWORD, /* Type of element */ \
0, /* ID to use store */ \
4, 4 /* min/max length */
#define CW_ACTION_IN_RADIO_ADMINISTRATIVE_STATE_WTP \
CW_ELEM_RADIO_ADMINISTRATIVE_STATE, /* Element ID*/ \
cw_in_radio_administrative_state_wtp, 0, /* start/end callback */ \
MBAG_DWORD, /* Type of element */ \
0, /* ID to use store */ \
4, 4 /* min/max length */
#define CW_ACTION_IN_MAXIMUM_MESSAGE_LENGTH \
CW_ELEM_MAXIMUM_MESSAGE_LENGTH, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_WORD, /* Type of element */ \
CW_ITEM_MAXIMUM_MESSAGE_LENGTH, /* ID to use store */ \
2, 2 /* min/max length */
#endif

393
src/cw/capwap_actions_ac.c Normal file
View File

@ -0,0 +1,393 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "capwap.h"
#include "action.h"
#include "capwap_items.h"
#include "capwap_actions.h"
#include "strheap.h"
#include "radio.h"
cw_action_in_t capwap_actions_ac_in[] = {
/* ------------------------------------------------------------------------------- */
/* Message Discovery Request */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_REQUEST, 0,
0, cw_in_check_disc_req}
,
/* Element Discovery Type */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_REQUEST, CW_ELEM_DISCOVERY_TYPE,
cw_in_generic, 0, MBAG_BYTE, CW_ITEM_DISCOVERY_TYPE, 1, 1, 1}
,
/* Element Frame Tunnel Mode */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_REQUEST,
CW_ACTION_IN_WTP_FRAME_TUNNEL_MODE, 1}
,
/* Element WTP Mac Tpe */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_REQUEST, CW_ACTION_IN_WTP_MAC_TYPE, 1}
,
/* Vendor Specific Payload */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_REQUEST,
CW_ACTION_IN_VENDOR_SPECIFIC_PAYLOAD}
,
/* Element WTP Descriptor */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_REQUEST, CW_ACTION_IN_WTP_DESCRIPTOR,
1}
,
/* Element WTP Board Data */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_REQUEST, CW_ACTION_IN_WTP_BOARD_DATA,
1}
,
/* Element WTP Board Data */
{0, 0, CW_STATE_CONFIGURE, CW_MSG_DISCOVERY_REQUEST, CW_ACTION_IN_WTP_BOARD_DATA,
1}
,
/* ------------------------------------------------------------------------------- */
/* Message: Join Request */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST, 0,
0, cw_in_check_join_req}
,
/* Location Data */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST, CW_ACTION_IN_LOCATION_DATA, 1}
,
/* WTP Board Data */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST, CW_ACTION_IN_WTP_BOARD_DATA, 1}
,
/* WTP Board Descriptor */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST, CW_ACTION_IN_WTP_DESCRIPTOR, 1}
,
/* Element WTP Name */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST, CW_ACTION_IN_WTP_NAME, 1}
,
/* Element Session ID */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST, CW_ACTION_IN_SESSION_ID, 1}
,
/* Element WTP Frame Tunnel Mode */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST, CW_ACTION_IN_WTP_FRAME_TUNNEL_MODE, 1}
,
/* Element WTP MAC Type */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST, CW_ACTION_IN_WTP_MAC_TYPE, 1}
,
/* Non-Mandatory Join Req Elements */
/* Element Vendor Specific Payload */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST, CW_ACTION_IN_VENDOR_SPECIFIC_PAYLOAD}
,
/* Maximum Message Length */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST, CW_ACTION_IN_MAXIMUM_MESSAGE_LENGTH}
,
/* ------------------------------------------------------------------------------- */
/* Message: Configuration Status Request */
{0, 0, CW_STATE_CONFIGURE, CW_MSG_CONFIGURATION_STATUS_REQUEST, 0,
0, 0}
,
/* Element: AC Name */
{0, 0, CW_STATE_CONFIGURE, CW_MSG_CONFIGURATION_STATUS_REQUEST,
CW_ACTION_IN_AC_NAME, 1}
,
/* Element: Statistics Timer */
{0, 0, CW_STATE_CONFIGURE, CW_MSG_CONFIGURATION_STATUS_REQUEST,
CW_ACTION_IN_STATISTICS_TIMER, 1}
,
/* Element: Statistics Timer */
{0, 0, CW_STATE_CONFIGURE, CW_MSG_CONFIGURATION_STATUS_REQUEST,
CW_ACTION_IN_WTP_REBOOT_STATISTICS, 1}
,
/* Element Vendor Specific Payload */
{0, 0, CW_STATE_CONFIGURE, CW_MSG_CONFIGURATION_STATUS_REQUEST,
CW_ACTION_IN_VENDOR_SPECIFIC_PAYLOAD}
,
/* ------------------------------------------------------------------------------- */
/* Message: Image Data Request - in Config State */
{0, 0, CW_STATE_CONFIGURE, CW_MSG_IMAGE_DATA_REQUEST, 0,
0, cw_in_check_img_data_req_ac}
,
{0, 0, CW_STATE_CONFIGURE, CW_MSG_IMAGE_DATA_REQUEST,
CW_ACTION_IN_IMAGE_IDENTIFIER,
0}
,
/* ------------------------------------------------------------------------------- */
/* Message: Change State Event Request - in Config State */
{0, 0, CW_STATE_CONFIGURE, CW_MSG_CHANGE_STATE_EVENT_REQUEST, 0,
cw_in_check_chng_state_evnt_req, 0}
,
/* Element: Result Code */
{0, 0, CW_STATE_CONFIGURE, CW_MSG_CHANGE_STATE_EVENT_REQUEST,
CW_ACTION_IN_RESULT_CODE, 1}
,
/* ------------------------------------------------------------------------------- */
/* Message: Change State Event Request - in Config State */
{0, 0, CW_STATE_RUN, CW_MSG_CHANGE_STATE_EVENT_REQUEST, 0,
cw_in_check_chng_state_evnt_req, 0}
,
/* ------------------------------------------------------------------------------- */
/* Message Image Data Response IN */
{0, 0, CW_STATE_IMAGE_DATA, CW_MSG_IMAGE_DATA_RESPONSE, 0,
0, cw_in_check_img_data_resp }
,
/* Element: Result Code */
{0, 0, CW_STATE_IMAGE_DATA, CW_MSG_IMAGE_DATA_RESPONSE,
CW_ACTION_IN_RESULT_CODE, 1}
,
/* ------------------------------------------------------------------------------- */
/* WTP Event Request */
{0, 0, CW_STATE_RUN, CW_MSG_WTP_EVENT_REQUEST, 0,
0, 0 }
,
/* Vendor Specific Payload */
{0, 0, CW_STATE_RUN, CW_MSG_WTP_EVENT_REQUEST,
CW_ACTION_IN_VENDOR_SPECIFIC_PAYLOAD}
,
/* ------------------------------------------------------------------------------- */
/* Echoh Request */
{0, 0, CW_STATE_RUN, CW_MSG_ECHO_REQUEST, 0,
0, 0 }
,
/* Message: Join Request */
{0, 0, CW_STATE_RUN, CW_MSG_CONFIGURATION_UPDATE_RESPONSE, 0,
0, 0}
,
{0, 0, 0}
};
cw_action_out_t capwap_actions_ac_out[] = {
{CW_MSG_DISCOVERY_RESPONSE, CW_ITEM_NONE}
,
/* AC Descriptor */
{CW_MSG_DISCOVERY_RESPONSE, CW_ITEM_AC_DESCRIPTOR, 0, CW_ELEM_AC_DESCRIPTOR,
NULL,cw_out_ac_descriptor, 0}
,
/* AC Name */
{CW_MSG_DISCOVERY_RESPONSE, CW_ITEM_AC_NAME, 0,
CW_ELEM_AC_NAME, NULL, cw_out_generic, cw_out_get_local}
,
/* List of CAPWAP Control IPv4 and IPv6 addresses */
{CW_MSG_DISCOVERY_RESPONSE, CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST, 0,
0, NULL, cw_out_capwap_control_ip_addr_list, cw_out_get_outgoing}
,
/* -------------------------------------------------------------------------------
* Join Response OUT
*/
{CW_MSG_JOIN_RESPONSE, CW_ITEM_NONE}
,
/* Result Code */
{CW_MSG_JOIN_RESPONSE, CW_ITEM_RESULT_CODE, 0,
CW_ELEM_RESULT_CODE, NULL,cw_out_generic, cw_out_get_outgoing, 1}
,
/* AC Descriptor */
{CW_MSG_JOIN_RESPONSE, CW_ITEM_AC_DESCRIPTOR, 0, CW_ELEM_AC_DESCRIPTOR,
NULL,cw_out_ac_descriptor, 0, 1}
,
/* AC Name */
{CW_MSG_JOIN_RESPONSE, CW_ITEM_AC_NAME, 0,
CW_ELEM_AC_NAME, NULL, cw_out_generic, cw_out_get_local,1}
,
/* Local IP Address */
{CW_MSG_JOIN_RESPONSE, CW_ITEM_CAPWAP_LOCAL_IP_ADDRESS, 0,
0, NULL, cw_out_capwap_local_ip_address, NULL,1}
,
/* List of CAPWAP Control IPv4 and IPv6 addresses */
{CW_MSG_JOIN_RESPONSE, CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST, 0,
0, NULL, cw_out_capwap_control_ip_addr_list, cw_out_get_outgoing}
,
/* -------------------------------------------------------------------------------
* Image Data Response OUT
*/
{CW_MSG_IMAGE_DATA_RESPONSE, CW_ITEM_NONE}
,
/* Result Code */
{CW_MSG_IMAGE_DATA_RESPONSE, CW_ITEM_RESULT_CODE, 0,
CW_ELEM_RESULT_CODE, NULL,cw_out_generic, cw_out_get_outgoing, 1}
,
/* -------------------------------------------------------------------------------
* Image Data Response OUT
*/
{CW_MSG_CONFIGURATION_STATUS_RESPONSE, CW_ITEM_NONE}
,
/* Result Code */
// {CW_MSG_CONFIGURATION_STATUS_RESPONSE, CW_ITEM_RESULT_CODE, 0,
// CW_ELEM_RESULT_CODE, NULL,cw_out_generic, cw_out_get_outgoing, 1}
// ,
/* -------------------------------------------------------------------------------
* Image Data Request OUT
*/
{CW_MSG_IMAGE_DATA_REQUEST, CW_ITEM_NONE}
,
/* Image Data */
{CW_MSG_IMAGE_DATA_REQUEST, CW_ITEM_IMAGE_FILEHANDLE, 0,
CW_ELEM_IMAGE_DATA, NULL,cw_out_image_data, cw_out_get_outgoing,0}
,
/* -------------------------------------------------------------------------------
* Change State Event Response OUT
*/
{CW_MSG_CHANGE_STATE_EVENT_RESPONSE, CW_ITEM_NONE}
,
/* -------------------------------------------------------------------------------
* WTP Event Response OUT
*/
{CW_MSG_WTP_EVENT_RESPONSE, CW_ITEM_NONE}
,
/* -------------------------------------------------------------------------------
* Echo Response OUT
*/
{CW_MSG_ECHO_RESPONSE, CW_ITEM_NONE}
,
/* -------------------------------------------------------------------------------
* Update Request OUT
*/
{CW_MSG_CONFIGURATION_UPDATE_REQUEST, CW_ITEM_NONE}
,
/* Result Code */
{CW_MSG_CONFIGURATION_UPDATE_REQUEST, CW_ITEM_WTP_NAME, 0,
CW_ELEM_WTP_NAME, NULL,cw_out_generic, cw_out_get_outgoing, 0}
,
/* Location Data */
{CW_MSG_CONFIGURATION_UPDATE_REQUEST, CW_ITEM_LOCATION_DATA, 0,
CW_ELEM_LOCATION_DATA, NULL,cw_out_generic, cw_out_get_outgoing,0}
,
/* End of list */
{0, 0}
};
#include "item.h"
int cw_register_actions_capwap_ac(struct cw_actiondef *def)
{
def->in = cw_actionlist_in_create();
def->out = cw_actionlist_out_create();
def->strmsg = cw_strheap_create();
def->strelem = cw_strheap_create();
def->wbids = intavltree_create();
def->items = cw_itemdefheap_create();
def->radioitems = cw_itemdefheap_create();
int rc;
rc = cw_actionlist_in_register_actions(def->in, capwap_actions_ac_in);
rc += cw_actionlist_out_register_actions(def->out, capwap_actions_ac_out);
rc += cw_strheap_register_strings(def->strmsg, capwap_strings_msg);
rc += cw_strheap_register_strings(def->strelem, capwap_strings_elem);
rc += cw_itemdefheap_register(def->items,capwap_itemdefs);
rc += cw_itemdefheap_register(def->radioitems,capwap_radioitemdefs);
intavltree_add(def->wbids,0);
return rc;
}

395
src/cw/capwap_actions_wtp.c Normal file
View File

@ -0,0 +1,395 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "capwap.h"
#include "action.h"
#include "capwap_items.h"
#include "capwap_actions.h"
#include "strheap.h"
#include "radio.h"
cw_action_in_t capwap_actions_wtp_in[] = {
/* ------------------------------------------------------------------------------- */
/* Message Discovery Response */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_RESPONSE, 0,
0, cw_in_check_disc_resp}
,
/* AC Descriptor */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_RESPONSE,
CW_ACTION_IN_AC_DESCRIPTOR, 1}
,
/* AC Name */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_RESPONSE,
CW_ACTION_IN_AC_NAME, 1}
,
/* CAPWAP Control IPv4 Address */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_RESPONSE,
CW_ACTION_IN_CAPWAP_CONTROL_IPV4_ADDRESS, 1}
,
/* CAPWAP Control IPv6 Address */
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_RESPONSE,
CW_ACTION_IN_CAPWAP_CONTROL_IPV6_ADDRESS, 1}
,
/* Vendor Specific Payload*/
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_RESPONSE,
CW_ACTION_IN_VENDOR_SPECIFIC_PAYLOAD, 0}
,
/* ------------------------------------------------------------------------------- */
/* Message Join Response */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_RESPONSE, 0,
0, cw_in_check_join_resp }
,
/* Result Code */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_RESPONSE,
CW_ACTION_IN_RESULT_CODE, 1}
,
/* AC Descriptor */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_RESPONSE,
CW_ACTION_IN_AC_DESCRIPTOR, 1}
,
/* AC Name */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_RESPONSE,
CW_ACTION_IN_AC_NAME, 1}
,
/* CAPWAP Control IPv4 Address */
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_RESPONSE,
CW_ACTION_IN_CAPWAP_CONTROL_IPV4_ADDRESS, 1}
,
/* ------------------------------------------------------------------------------- */
/* Message Image Data Response */
{0, 0, CW_STATE_CONFIGURE, CW_MSG_IMAGE_DATA_RESPONSE, 0,
0, cw_in_check_img_data_resp }
,
/* Element: Result Code */
{0, 0, CW_STATE_CONFIGURE, CW_MSG_IMAGE_DATA_RESPONSE,
CW_ACTION_IN_RESULT_CODE, 1}
,
/* ------------------------------------------------------------------------------- */
/* Message Image Data Request IN */
{0, 0, CW_STATE_IMAGE_DATA, CW_MSG_IMAGE_DATA_REQUEST, 0,
0, cw_in_check_img_data_req_wtp }
,
/* ------------------------------------------------------------------------------- */
/* Message Config Status Response IN */
{0, 0, CW_STATE_CONFIGURE, CW_MSG_CONFIGURATION_STATUS_RESPONSE, 0,
0,0 }
,
{0, 0, CW_STATE_CONFIGURE, CW_MSG_CONFIGURATION_STATUS_RESPONSE,
CW_ACTION_IN_CAPWAP_TIMERS, 1}
,
{0, 0, CW_STATE_CONFIGURE, CW_MSG_CONFIGURATION_STATUS_RESPONSE,
CW_ACTION_IN_IDLE_TIMEOUT, 1}
,
// {0, 0, CW_STATE_CONFIGURE, CW_MSG_CONFIGURATION_STATUS_RESPONSE,
// CW_ACTION_IN_DECRYPTION_ERROR_REPORT_PERIOD, 1}
// ,
{0, 0, CW_STATE_CONFIGURE, CW_MSG_CONFIGURATION_STATUS_RESPONSE,
CW_ACTION_IN_VENDOR_SPECIFIC_PAYLOAD, 0}
,
/* ------------------------------------------------------------------------------- */
/* Message Change State Response IN */
{0, 0, CW_STATE_CONFIGURE, CW_MSG_CHANGE_STATE_EVENT_RESPONSE, 0,
0, cw_in_check_cfg_update_req }
,
/* ------------------------------------------------------------------------------- */
/* Message Configuration Update Request IN */
{0, 0, CW_STATE_RUN, CW_MSG_CONFIGURATION_UPDATE_REQUEST,
0, 0,0 }
,
{0, 0, CW_STATE_RUN, CW_MSG_CONFIGURATION_UPDATE_REQUEST,
CW_ACTION_IN_CAPWAP_TIMERS, 0}
,
{0, 0, CW_STATE_RUN, CW_MSG_CONFIGURATION_UPDATE_REQUEST,
CW_ACTION_IN_RADIO_ADMINISTRATIVE_STATE_WTP, 0}
,
{0, 0, CW_STATE_RUN, CW_MSG_CONFIGURATION_UPDATE_REQUEST,
CW_ACTION_IN_WTP_NAME, 0}
,
/* Location Data */
{0, 0, CW_STATE_RUN, CW_MSG_CONFIGURATION_UPDATE_REQUEST,
CW_ACTION_IN_LOCATION_DATA, 0}
,
/* Element: Vendor Specific */
{0, 0, CW_STATE_RUN, CW_MSG_CONFIGURATION_UPDATE_REQUEST,
CW_ACTION_IN_VENDOR_SPECIFIC_PAYLOAD, 0}
,
/* ------------------------------------------------------------------------------- */
/* Echo Response Response IN */
{0, 0, CW_STATE_RUN, CW_MSG_ECHO_RESPONSE, 0,
0,0 }
,
/* Element: Vendor Specific */
{0, 0, CW_STATE_RUN, CW_MSG_ECHO_RESPONSE,
CW_ACTION_IN_VENDOR_SPECIFIC_PAYLOAD, 0}
,
{0, 0, 0}
};
cw_action_out_t capwap_actions_wtp_out[] = {
/* -------------------------------------------------------------------------------
* Discovery Request OUT
*/
{CW_MSG_DISCOVERY_REQUEST, CW_ITEM_NONE}
,
/* AC Name */
{CW_MSG_DISCOVERY_REQUEST, CW_ITEM_DISCOVERY_TYPE, 0,
CW_ELEM_DISCOVERY_TYPE, NULL,cw_out_generic, cw_out_get_outgoing}
,
{CW_MSG_DISCOVERY_REQUEST, CW_ITEM_WTP_FRAME_TUNNEL_MODE, 0,
CW_ELEM_WTP_FRAME_TUNNEL_MODE, NULL,cw_out_generic, cw_out_get_local,1}
,
{CW_MSG_DISCOVERY_REQUEST, CW_ITEM_WTP_MAC_TYPE, 0,
CW_ELEM_WTP_MAC_TYPE, NULL,cw_out_generic, cw_out_get_local,1}
,
/* WTP Board Data */
{CW_MSG_DISCOVERY_REQUEST, CW_ITEM_WTP_BOARD_DATA, 0,
CW_ELEM_WTP_BOARD_DATA, NULL,cw_out_wtp_board_data, cw_out_get_outgoing,1}
,
/* WTP Descriptor */
{CW_MSG_DISCOVERY_REQUEST, CW_ITEM_WTP_DESCRIPTOR, 0,
CW_ELEM_WTP_DESCRIPTOR, NULL,cw_out_wtp_descriptor, NULL,1}
,
/* -------------------------------------------------------------------------------
* Join Request OUT
*/
{CW_MSG_JOIN_REQUEST, CW_ITEM_NONE}
,
/* Location Data */
{CW_MSG_JOIN_REQUEST, CW_ITEM_LOCATION_DATA, 0,
CW_ELEM_LOCATION_DATA, NULL,cw_out_generic, cw_out_get_config,1}
,
/* WTP Board Data */
{CW_MSG_JOIN_REQUEST, CW_ITEM_WTP_BOARD_DATA, 0,
CW_ELEM_WTP_BOARD_DATA, NULL,cw_out_wtp_board_data, cw_out_get_outgoing,1}
,
/* WTP Descriptor */
{CW_MSG_JOIN_REQUEST, CW_ITEM_WTP_DESCRIPTOR, 0,
CW_ELEM_WTP_DESCRIPTOR, NULL,cw_out_wtp_descriptor, NULL,1}
,
/* WTP Name */
{CW_MSG_JOIN_REQUEST, CW_ITEM_WTP_NAME, 0,
CW_ELEM_WTP_NAME, NULL,cw_out_generic, cw_out_get_config,1}
,
/* WTP MAC Type */
{CW_MSG_JOIN_REQUEST, CW_ITEM_WTP_MAC_TYPE, 0,
CW_ELEM_WTP_MAC_TYPE, NULL,cw_out_generic, cw_out_get_config,1}
,
/* WTP MAC Type */
{CW_MSG_JOIN_REQUEST, CW_ITEM_WTP_FRAME_TUNNEL_MODE, 0,
CW_ELEM_WTP_FRAME_TUNNEL_MODE, NULL,cw_out_generic, cw_out_get_config,1}
,
/* Session ID */
{CW_MSG_JOIN_REQUEST, CW_ITEM_SESSION_ID, 0,
CW_ELEM_SESSION_ID, NULL,cw_out_generic, cw_out_get_session_id,1}
,
/* -------------------------------------------------------------------------------
* Image Data Request OUT
*/
{CW_MSG_IMAGE_DATA_REQUEST, CW_ITEM_NONE}
,
/* Image Identifier */
{CW_MSG_IMAGE_DATA_REQUEST, CW_ITEM_IMAGE_IDENTIFIER, 0,
CW_ELEM_IMAGE_IDENTIFIER, NULL,cw_out_generic, cw_out_get_outgoing,0}
,
/* -------------------------------------------------------------------------------
* Image Data Response OUT
*/
{CW_MSG_IMAGE_DATA_RESPONSE, CW_ITEM_NONE}
,
/* Result Code */
{CW_MSG_IMAGE_DATA_RESPONSE, CW_ITEM_RESULT_CODE, 0,
CW_ELEM_RESULT_CODE, NULL,cw_out_generic, cw_out_get_outgoing, 1}
,
/* -------------------------------------------------------------------------------
* Configuration Status Request OUT
*/
{CW_MSG_CONFIGURATION_STATUS_REQUEST, CW_ITEM_NONE}
,
/* AC Name */
{CW_MSG_CONFIGURATION_STATUS_REQUEST, CW_ITEM_AC_NAME, 0,
CW_ELEM_AC_NAME, NULL, cw_out_generic, cw_out_get_local,1}
,
/* AC Name with Priority */
{CW_MSG_CONFIGURATION_STATUS_REQUEST, CW_ITEM_AC_NAME_WITH_PRIORITY, 0,
CW_ELEM_AC_NAME_WITH_PRIORITY, NULL, cw_out_ac_name_with_priority, cw_out_get_config,1}
,
/* Radio Admin State */
{CW_MSG_CONFIGURATION_STATUS_REQUEST, CW_ITEM_RADIO_ADMINISTRATIVE_STATE, 0,
CW_ELEM_RADIO_ADMINISTRATIVE_STATE, NULL, cw_out_radio_administrative_states, cw_out_get_config,1}
,
/* -------------------------------------------------------------------------------
* Configuration Status Request OUT
*/
{CW_MSG_CHANGE_STATE_EVENT_REQUEST, CW_ITEM_NONE}
,
/* Radio Ooerational State */
{CW_MSG_CHANGE_STATE_EVENT_REQUEST, CW_ITEM_RADIO_OPER_STATE, 0,
0, NULL, cw_out_radio_operational_states, cw_out_get_config,1}
,
/* -------------------------------------------------------------------------------
* Echo Request Request OUT
*/
{CW_MSG_ECHO_REQUEST, CW_ITEM_NONE}
,
/* -------------------------------------------------------------------------------
* Configuration Update Response
*/
{CW_MSG_CONFIGURATION_UPDATE_RESPONSE, CW_ITEM_NONE}
,
/* Radio Oper State */
{CW_MSG_CONFIGURATION_UPDATE_RESPONSE, CW_ITEM_RADIO_OPER_STATE, 0,
0, NULL, cw_out_radio_operational_states, cw_out_get_config,1}
,
{0, 0}
};
int cw_register_actions_capwap_wtp(struct cw_actiondef *def)
{
def->in = cw_actionlist_in_create();
def->out = cw_actionlist_out_create();
def->strmsg = cw_strheap_create();
def->strelem = cw_strheap_create();
def->items = cw_itemdefheap_create();
def->radioitems = cw_itemdefheap_create();
int rc;
rc = cw_actionlist_in_register_actions(def->in, capwap_actions_wtp_in);
rc += cw_actionlist_out_register_actions(def->out, capwap_actions_wtp_out);
rc += cw_strheap_register_strings(def->strmsg, capwap_strings_msg);
rc += cw_strheap_register_strings(def->strelem, capwap_strings_elem);
rc += cw_itemdefheap_register(def->items,capwap_itemdefs);
rc += cw_itemdefheap_register(def->radioitems,capwap_radioitemdefs);
return rc;
}

239
src/cw/capwap_cisco.h Normal file
View File

@ -0,0 +1,239 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Cisco specific CAPWAP definitions
*/
#ifndef __CAPWAP_CISCO_H
#define __CAPWAP_CISCO_H
#include <string.h>
#include <time.h>
#include "lwapp.h"
#include "capwap.h"
#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_MWAR LW_ELEM_AC_DESCRIPTOR /* 6 */
#define CW_CISCO_ADD_WLAN LW_ELEM_80211_ADD_WLAN /* 7 */
#define CW_CISCO_WTP_RADIO_CFG 8
#define CW_CISCO_MULTI_DOMAIN_CAPAB LW_ELEM_80211_MULTI_DOMAIN_CAPABILITY /* 10 */
#define CW_CISCO_MAC_OPERATION LW_ELEM_80211_MAC_OPERATION /* 11 */
#define CW_CISCO_TX_POWER LW_ELEM_80211_TX_POWER /* 12 */
#define CW_CISCO_TX_POWER_LEVELS LW_ELEM_80211_TX_POWER_LEVELS /* 13 */
#define CW_CISCO_DIRECT_SEQUENCE_CONTROL LW_ELEM_DIRECT_SEQUENCE_CONTROL /* 14 */
#define CW_CISCO_SUPPORTED_RATES LW_ELEM_80211_RATE_SET /* 16 */
#define CW_CISCO_80211_DELETE_WLAN LW_ELEM_80211_DELETE_WLAN /* 28 */
#define CW_CISCO_MWAR_NAME LW_ELEM_AC_NAME /* 31 */
#define CW_CISCO_LOCATION_DATA LW_ELEM_LOCATION_DATA /* 35 */
#define CW_CISCO_STATISTICS_TIMER LW_ELEM_STATISTICS_TIMER /* 37 */
#define CW_CISCO_ANTENNA_PAYLOAD 41
#define CW_CISCO_CERTIFICATE LW_ELEM_CERTIFICATE /* 44 */
#define CW_CISCO_WTP_BOARD_DATA LW_ELEM_WTP_BOARD_DATA /* 50 */
#define CW_CISCO_AP_MODE_AND_TYPE LW_ELEM_80211_WTP_MODE_AND_TYPE /* 54 */
#define CW_CISCO_AP_QOS LW_ELEM_QOS /* 57 */
#define CW_CISCO_AC_IPV4_LIST LW_ELEM_AC_IPV4_LIST /* 59 */
#define CW_CISCO_AP_STATIC_IP_ADDR 83
#define CW_CISCO_SIG_PAYLOAD 84
#define CW_CISCO_SIG_TOGGLE 87
#define CW_CISCO_AC_NAME_WITH_INDEX 91
#define CW_CISCO_SPAM_DOMAIN_SECRET 96
#define CW_CISCO_SPAM_VENDOR_SPECIFIC 104
#define CW_CISCO_AP_UPTIME 108
#define CW_CISCO_AP_GROUP_NAME 123
#define CW_CISCO_SPAM_AP_LED_STATE 125
#define CW_CISCO_AP_MODEL 127
#define CW_CISCO_AP_RESET_BUTTON_STATE 128
#define CW_CISCO_AP_LED_STATE_CONFIG 125
#define CW_CISCO_AP_REGULATORY_DOMAIN 126
#define CW_CISCO_LWAPP_CHANNEL_POWER 134
#define CW_CISCO_AP_PRE_STD_SWITCH_CONFIG 137
#define CW_CISCO_AP_POWER_INJECTOR_CONFIG 138
#define CW_CISCO_AP_MINIOS_VERSION 149
#define CW_CISCO_AP_TIMESYNC 151
#define CW_CISCO_AP_DOMAIN 169
#define CW_CISCO_AP_DNS 170
#define CW_CISCO_AP_BACKUP_SOFTWARE_VERSION 183
#define CW_CISCO_BOARD_DATA_OPTIONS 207
#define CW_CISCO_MWAR_TYPE 208
#define CW_CISCO_80211_ASSOC_LIMIT 213
#define CW_CISCO_TLV_PAYLOAD 215
#define CW_CISCO_AP_LOG_FACILITY 224
#define CW_CISCO_AP_RETRANSMIT_PARAM 240
#define CW_CISCO_AP_VENUE_SETTINGS 249
/**
* Add a Cisco AP Timesync message element to a buffer
* @param dst destination buffer
* @param time a unix timestamp
* @param type of time
* @return number of bytes put (5)
*/
static inline int cw_put_cisco_ap_timesync(uint8_t * dst, time_t time, uint8_t type)
{
cw_put_dword(dst , time);
cw_put_byte(dst + 4, type);
return 5;
}
int cw_out_cisco_ap_timesync(struct conn *conn,struct cw_action_out * a,uint8_t *dst);
/**
* Add a Cisco RAD Name message element to buffer
* @param dst destination buffer
* @param name RAD name, zero terminated
* @return number of bytes put
*/
//static inline int cw_addelem_cisco_rad_name(uint8_t * dst, uint8_t * name)
//{
// return cw_addelem_vendor_specific_payload(dst, CW_VENDOR_ID_CISCO, CW_CISCO_RAD_NAME, name,
// strlen((char *) name));
//}
/**
* Add a Cisco Group Name message element to buffer
* @param dst destination buffer
* @param name Group name, zero terminated
* @return number of bytes put
*/
/*
static inline int cw_addelem_cisco_ap_group_name(uint8_t * dst, uint8_t * name){
return cw_addelem_vendor_specific_payload(dst, CW_VENDOR_ID_CISCO, CW_CISCO_AP_GROUP_NAME, name,
strlen((char *) name));
}
*/
static inline int cw_addelem_cisco_ap_regulatory_domain(uint8_t *dst, struct radioinfo * ri){
uint8_t *d=dst+10;
d+=cw_put_byte(d,ri->rid); /* Band ID */
d+=cw_put_byte(d,1); /* Set True/False */
d+=cw_put_byte(d,ri->rid); /* Slot ID */
d+=cw_put_word(d,ri->regDomain);
return 5 + cw_put_elem_vendor_hdr(dst, CW_VENDOR_ID_CISCO, CW_CISCO_AP_REGULATORY_DOMAIN, 5);
}
/**
* Add a Cisco MWAR message element.
* @param dst destinnation buffer
* @param acinfo AC data
* @return number of bytes put
*
* This message elemet is basically an LWAPP AC Descriptor
* encapsulated in a CAPWAP vendor specific payload message
*/
/*
static inline int cw_addelem_cisco_mwar(uint8_t *dst, struct ac_info *acinfo){
int l = lw_put_ac_descriptor(dst+10,acinfo);
return l+cw_put_elem_vendor_hdr(dst,CW_VENDOR_ID_CISCO,CW_CISCO_MWAR,l);
}
*/
/**
* Add a Cisco Certificate payload message element
* @param dst destination buffer
* @param src pointer to DER certificate
* @param len length of certificate
* @return number of bytes put
*/
static inline int cw_addelem_cisco_certificate(uint8_t*dst,uint8_t*src,int len){
int l = lw_put_certificate(dst+10,src,len);
return l+cw_put_elem_vendor_hdr(dst,CW_VENDOR_ID_CISCO,CW_CISCO_CERTIFICATE,l);
}
/*
static inline int cw_addelem_cisco_wtp_radio_cfg(uint8_t * dst,struct radioinfo *ri){
int l = lw_put_80211_wtp_wlan_radio_configuration(dst+10,ri);
return l+cw_put_elem_vendor_hdr(dst,CW_VENDOR_ID_CISCO,CW_CISCO_STATION_CFG,l);
}
*/
static inline int cw_readelem_cisco_station_cfg(uint8_t *src,int len){
// lw_readelem_
return 0;
}
extern const char * cw_cisco_id_to_str(int elem_id);
int cw_readelem_cisco_wtp_radio_cfg(int elem_id,uint8_t *elem, int len,struct radioinfo *ri);
int cw_addelem_cisco_wtp_radio_cfg(uint8_t*dst,struct radioinfo * ri);
extern int cw_out_cisco_ac_descriptor(struct conn *conn,struct cw_action_out * a,uint8_t *dst) ;
int cw_in_cisco_image_identifier(struct conn *conn,struct cw_action_in * a,uint8_t *data,int len,struct sockaddr *from);
int cw_in_cipwap_wtp_descriptor(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len,struct sockaddr *from);
int cw_in_check_cipwap_join_req(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len,struct sockaddr *from);
int cw_out_cisco_wtp_radio_cfg(struct conn *conn, struct cw_action_out *a, uint8_t * dst);
int cw_in_cisco_radio_administrative_state(struct conn *conn, struct cw_action_in *a, uint8_t * data, int len,
struct sockaddr *from);
int cw_in_cisco_radio_administrative_state_wtp(struct conn *conn, struct cw_action_in *a, uint8_t * data, int len,
struct sockaddr *from);
int cw_in_cisco_radio_cfg(struct conn *conn, struct cw_action_in *a, uint8_t * data, int len,
struct sockaddr *from);
int cw_in_cisco_add_wlan(struct conn *conn, struct cw_action_in *a, uint8_t * data, int len,
struct sockaddr *from);
#endif

17
src/cw/capwap_crypto.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef __CAPWAP_CRYPTO_H
#define __CAPWAP_CRYPTO_H
#include <nettle/md5.h>
/**
*@file
*@brief
*/
/** MD5 digest size, 16 bytes */
#define CW_MD5_DIGEST_SIZE MD5_DIGEST_SIZE
int cw_fgetmd5sum(uint8_t *digest, FILE *infile);
#endif

148
src/cw/capwap_items.c Normal file
View File

@ -0,0 +1,148 @@
#include "item.h"
#include "capwap_items.h"
const char CW_ITEM_IDLE_TIMEOUT[]="idle_timeout";
const char CW_ITEM_DISCOVERY_TYPE[]="discovery_type";
const char CW_ITEM_WTP_NAME[]="wtp_name";
const char CW_ITEM_WTP_MAC_TYPE[]="wtp_mac_type";
const char CW_ITEM_WTP_FRAME_TUNNEL_MODE[]="wtp_frame_tunnel_mode";
const char CW_ITEM_WTP_RADIOS_IN_USE[]="max_radios";
const char CW_ITEM_WTP_MAX_RADIOS[]="radios_in_use";
/*
const char CW_ITEM_WTP_HARDWARE_VENDOR=
*/
const char CW_ITEM_WTP_HARDWARE_VERSION[]="wtp_hardware_version";
const char CW_ITEM_WTP_SOFTWARE_VERSION[]="wtp_software_version";
/*
const char CW_ITEM_WTP_SOFTWARE_VENDOR,
*/
/*
const char CW_ITEM_WTP_BOOTLOADER_VENDOR,
*/
const char CW_ITEM_WTP_BOOTLOADER_VERSION[]="wtp_bootloader_version";
/*
const char CW_ITEM_WTP_OTHERSOFTWARE_VENDOR,
const char CW_ITEM_WTP_OTHERSOFTWARE_VERSION,
*/
const char CW_ITEM_WTP_BOARD_DATA[]="wtp_board_data";
const char CW_ITEM_WTP_DESCRIPTOR[]="0wtp_descriptor";
const char CW_ITEM_CAPWAP_TIMERS[]="capwap_timers";
const char CW_ITEM_RADIO_ADMINISTRATIVE_STATE[]="radio_admin_state";
const char CW_ITEM_AC_NAME[]="ac_name";
const char CW_ITEM_AC_DESCRIPTOR[]="ac_descriptor";
const char CW_ITEM_RESULT_CODE[]="result_code";
const char CW_ITEM_AC_STATUS[]="ac_status";
const char CW_ITEM_AC_HARDWARE_VERSION[]="ac_hardware_version";
const char CW_ITEM_AC_SOFTWARE_VERSION[]="ac_software_version";
const char CW_ITEM_AC_IP_LIST[]="ac_ip_list";
const char CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST[]="capwap_ctrl_ip_addr";
const char CW_ITEM_CAPWAP_LOCAL_IP_ADDRESS[]="capwap_local_ip_addr";
const char CW_ITEM_LOCATION_DATA[]="location_data";
const char CW_ITEM_SESSION_ID[]="session_id";
const char CW_ITEM_AC_TIMESTAMP[]="ac_timestamp";
const char CW_ITEM_STATISTICS_TIMER[]="statistics_timer";
const char CW_ITEM_WTP_REBOOT_STATISTICS[]="wtp_reboot_statistics";
const char CW_ITEM_IMAGE_IDENTIFIER[]="image_identifier";
const char CW_ITEM_AC_HASH_VALUE[]="ac_hash_value";
const char CW_ITEM_AC_NAME_WITH_PRIORITY[]="ac_name_with_priority";
const char CW_ITEM_MAXIMUM_MESSAGE_LENGTH[]="maximum_message_length";
/* CIPWAP and Cisco */
const char CW_ITEM_WTP_GROUP_NAME[]="wtp_group_name";
/* Other Items */
const char CW_ITEM_AC_IMAGE_DIR[]="ac_img_dir"; /* Path where WTP images are stored */
const char CW_ITEM_IMAGE_FILENAME[]="img_filename"; /* Full path of image filename */
const char CW_ITEM_DISCOVERIES[]="discoveries";
/** FILE handle for uploading and downloading images */
const char CW_ITEM_IMAGE_FILEHANDLE[]="image_file_handle";
const char CW_ITEM_RADIO_CFG[]="radio_cfg";
const char CW_ITEM_AP_MODE_AND_TYPE[]="cisco_ap_mode_and_type";
const char CW_ITEM_CISCO_BOARD_DATA_OPTIONS[]="cisco_board_data_options";
const char CW_ITEM_RADIOS[]="radios";
const char CW_ITEM_RADIO_OPER_STATE[]="radio_oper_state";
const char CW_ITEM_WTP_BOARD_VENDOR[]="vendor_id";
const char CW_ITEM_WTP_BOARD_MODELNO[]="model_no";
const char CW_ITEM_WTP_BOARD_MACADDRESS[]="wtp_board_macadddress";
const char CW_ITEM_WTP_BOARD_ID[]="wtp_board_id";
const char CW_ITEM_WTP_BOARD_REVISION[]="wtp_board_revision";
const char CW_ITEM_WTP_BOARD_SERIALNO[]="serial_no";
const char CW_ITEM_RADIO_INFOS[]="radio_infos";
//const char CW_ITEM_XY[]="wtp_name";
struct cw_itemdef capwap_itemdefs[] = {
{CW_ITEM_WTP_NAME,CW_ITEM_NONE,MBAG_STR},
{CW_ITEM_WTP_MAC_TYPE,CW_ITEM_NONE,MBAG_BYTE},
{CW_ITEM_WTP_FRAME_TUNNEL_MODE,CW_ITEM_NONE,MBAG_BYTE},
{CW_ITEM_LOCATION_DATA,CW_ITEM_NONE,MBAG_STR},
{CW_ITEM_WTP_HARDWARE_VERSION,CW_ITEM_NONE,MBAG_VENDORSTR},
{CW_ITEM_WTP_SOFTWARE_VERSION,CW_ITEM_NONE,MBAG_VENDORSTR},
{CW_ITEM_WTP_GROUP_NAME,CW_ITEM_NONE,MBAG_STR},
{CW_ITEM_MAXIMUM_MESSAGE_LENGTH,CW_ITEM_NONE,MBAG_WORD},
{CW_ITEM_STATISTICS_TIMER,CW_ITEM_NONE,MBAG_WORD},
{CW_ITEM_IDLE_TIMEOUT,CW_ITEM_NONE,MBAG_DWORD},
{CW_ITEM_CAPWAP_TIMERS,CW_ITEM_NONE,MBAG_WORD},
{CW_ITEM_AC_NAME_WITH_PRIORITY,CW_ITEM_ANY,MBAG_STR},
{CW_ITEM_AP_MODE_AND_TYPE,CW_ITEM_NONE,MBAG_WORD},
/* Board Data */
{CW_ITEM_WTP_BOARD_DATA,CW_ITEM_NONE,MBAG_MBAG},
{CW_ITEM_WTP_BOARD_DATA,CW_ITEM_WTP_BOARD_VENDOR,MBAG_DWORD},
{CW_ITEM_WTP_BOARD_DATA,CW_ITEM_WTP_BOARD_MODELNO,MBAG_BSTR16},
{CW_ITEM_WTP_BOARD_DATA,CW_ITEM_WTP_BOARD_SERIALNO,MBAG_BSTR16},
/* Cisco Specific items, should be moved to a file like
cisco_items or so */
{CW_ITEM_AP_MODE_AND_TYPE,CW_ITEM_NONE,MBAG_WORD},
{CW_ITEM_CISCO_BOARD_DATA_OPTIONS,CW_ITEM_NONE,MBAG_BSTR16},
{CW_ITEM_NONE}
};
struct cw_itemdef capwap_radiodefs[] = {
{CW_ITEM_NONE}
};

180
src/cw/capwap_items.h Normal file
View File

@ -0,0 +1,180 @@
#ifndef __CAPWAP_ITEMS_H
#define __CAPWAP_ITEMS_H
#include "item.h"
/*
CW_ITEM_NONE=0,
CW_ITEM_IDLE_TIMEOUT,
CW_ITEM_DISCOVERY_TYPE,
CW_ITEM_WTP_NAME,
CW_ITEM_WTP_BOARD_VENDOR,
CW_ITEM_WTP_BOARD_MODELNO,
CW_ITEM_WTP_BOARD_MACADDRESS,
CW_ITEM_WTP_BOARD_ID,
CW_ITEM_WTP_BOARD_REVISION,
CW_ITEM_WTP_BOARD_SERIALNO,
CW_ITEM_WTP_MAC_TYPE,
CW_ITEM_WTP_FRAME_TUNNEL_MODE,
CW_ITEM_WTP_RADIOS_IN_USE,
CW_ITEM_WTP_MAX_RADIOS,
CW_ITEM_WTP_HARDWARE_VENDOR,
CW_ITEM_WTP_HARDWARE_VERSION,
CW_ITEM_WTP_SOFTWARE_VENDOR,
CW_ITEM_WTP_SOFTWARE_VERSION,
CW_ITEM_WTP_BOOTLOADER_VENDOR,
CW_ITEM_WTP_BOOTLOADER_VERSION,
CW_ITEM_WTP_OTHERSOFTWARE_VENDOR,
CW_ITEM_WTP_OTHERSOFTWARE_VERSION,
CW_ITEM_WTP_BOARD_DATA,
CW_ITEM_WTP_DESCRIPTOR,
CW_ITEM_CAPWAP_TIMERS,
CW_ITEM_RADIO_ADMINISTRATIVE_STATE,
CW_ITEM_AC_NAME,
CW_ITEM_AC_DESCRIPTOR,
CW_ITEM_RESULT_CODE,
CW_ITEM_AC_STATUS,
CW_ITEM_AC_HARDWARE_VERSION,
CW_ITEM_AC_SOFTWARE_VERSION,
CW_ITEM_AC_IP_LIST,
CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST,
CW_ITEM_CAPWAP_LOCAL_IP_ADDRESS,
CW_ITEM_LOCATION_DATA,
CW_ITEM_SESSION_ID,
CW_ITEM_AC_TIMESTAMP,
CW_ITEM_STATISTICS_TIMER,
CW_ITEM_WTP_REBOOT_STATISTICS,
CW_ITEM_IMAGE_IDENTIFIER,
CW_ITEM_AC_HASH_VALUE,
CW_ITEM_AC_NAME_WITH_PRIORITY,
CW_ITEM_MAXIMUM_MESSAGE_LENGTH,
CW_ITEM_WTP_GROUP_NAME,
CW_ITEM_AC_IMAGE_DIR,
CW_ITEM_IMAGE_FILENAME,
CW_ITEM_DISCOVERIES,
CW_ITEM_IMAGE_FILEHANDLE,
CW_ITEM_RADIO_CFG,
CW_ITEM_AP_MODE_AND_TYPE,
CW_ITEM_CISCO_BOARD_DATA_OPTIONS,
CW_ITEM_RADIOS,
CW_ITEM_RADIO_OPER_STATE,
*/
extern const char CW_ITEM_IDLE_TIMEOUT[];
extern const char CW_ITEM_DISCOVERY_TYPE[];
extern const char CW_ITEM_WTP_NAME[];
/*
extern const char CW_ITEM_WTP_BOARD_VENDOR,
extern const char CW_ITEM_WTP_BOARD_MODELNO,
extern const char CW_ITEM_WTP_BOARD_MACADDRESS,
extern const char CW_ITEM_WTP_BOARD_ID,
extern const char CW_ITEM_WTP_BOARD_REVISION,
extern const char CW_ITEM_WTP_BOARD_SERIALNO,
*/
extern const char CW_ITEM_WTP_MAC_TYPE[];
extern const char CW_ITEM_WTP_FRAME_TUNNEL_MODE[];
/*
extern const char CW_ITEM_WTP_RADIOS_IN_USE=
extern const char CW_ITEM_WTP_MAX_RADIOS,
*/
/*
extern const char CW_ITEM_WTP_HARDWARE_VENDOR=
extern const char CW_ITEM_WTP_HARDWARE_VERSION="
*/
/*
extern const char CW_ITEM_WTP_SOFTWARE_VENDOR,
extern const char CW_ITEM_WTP_SOFTWARE_VERSION,
extern const char CW_ITEM_WTP_BOOTLOADER_VENDOR,
extern const char CW_ITEM_WTP_BOOTLOADER_VERSION,
extern const char CW_ITEM_WTP_OTHERSOFTWARE_VENDOR,
extern const char CW_ITEM_WTP_OTHERSOFTWARE_VERSION,
*/
extern const char CW_ITEM_WTP_BOARD_DATA[];
extern const char CW_ITEM_WTP_DESCRIPTOR[];
extern const char CW_ITEM_CAPWAP_TIMERS[];
extern const char CW_ITEM_RADIO_ADMINISTRATIVE_STATE[];
extern const char CW_ITEM_AC_NAME[];
extern const char CW_ITEM_AC_DESCRIPTOR[];
extern const char CW_ITEM_RESULT_CODE[];
extern const char CW_ITEM_AC_STATUS[];
extern const char CW_ITEM_AC_HARDWARE_VERSION[];
extern const char CW_ITEM_AC_SOFTWARE_VERSION[];
extern const char CW_ITEM_AC_IP_LIST[];
extern const char CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST[];
extern const char CW_ITEM_CAPWAP_LOCAL_IP_ADDRESS[];
extern const char CW_ITEM_LOCATION_DATA[];
extern const char CW_ITEM_SESSION_ID[];
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[];
/* CIPWAP and Cisco */
extern const char CW_ITEM_WTP_GROUP_NAME[];
/* Other Items */
extern const char CW_ITEM_AC_IMAGE_DIR[]; /* Path where WTP images are stored */
extern const char CW_ITEM_IMAGE_FILENAME[]; /* Full path of image filename */
extern const char CW_ITEM_DISCOVERIES[];
/** FILE handle for uploading and downloading images */
extern const char CW_ITEM_IMAGE_FILEHANDLE[];
extern const char CW_ITEM_RADIO_CFG[];
extern const char CW_ITEM_AP_MODE_AND_TYPE[];
extern const char CW_ITEM_CISCO_BOARD_DATA_OPTIONS[];
extern const char CW_ITEM_RADIOS[];
extern const char CW_ITEM_RADIO_OPER_STATE[];
extern const char CW_ITEM_WTP_BOARD_VENDOR[];
extern const char CW_ITEM_WTP_BOARD_MODELNO[];
extern const char CW_ITEM_WTP_BOARD_MACADDRESS[];
extern const char CW_ITEM_WTP_BOARD_ID[];
extern const char CW_ITEM_WTP_BOARD_REVISION[];
extern const char CW_ITEM_WTP_BOARD_SERIALNO[];
extern const char CW_ITEM_WTP_SOFTWARE_VERSION[];
extern const char CW_ITEM_WTP_HARDWARE_VERSION[];
extern const char CW_ITEM_WTP_BOOTLOADER_VERSION[];
extern const char CW_ITEM_WTP_RADIOS_IN_USE[];
extern const char CW_ITEM_WTP_MAX_RADIOS[];
extern const char CW_ITEM_RADIO_INFOS[];
extern struct cw_itemdef capwap_itemdefs[];
#endif

25
src/cw/capwap_msg_new.c Normal file
View File

@ -0,0 +1,25 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "capwap.h"
struct capwap_msg * capwap_msg_new()
{
}

View File

@ -0,0 +1,67 @@
#include "capwap.h"
struct cw_strlist_elem capwap_strings_elem[] = {
{CW_ELEM_AC_DESCRIPTOR, "AC Descriptor"},
{CW_ELEM_AC_IPV4_LIST, "AC IPv4 List"},
{CW_ELEM_AC_IPV6_LIST, "AC IPv6 List"},
{CW_ELEM_AC_NAME, "AC Name"},
{CW_ELEM_AC_NAME_WITH_PRIORITY, "AC Name with Priority"},
// {CW_ELEM_AC_NAME_WITH_INDEX, "AC Name with Index"},
{CW_ELEM_AC_TIMESTAMP, "AC Timestamp"},
{CW_ELEM_ADD_MAC_ACL_ENTRY, "Add MAC ACL Entry"},
{CW_ELEM_ADD_STATION, "Add Station"},
{CW_ELEM_RESERVED_9, "Reserved 9"},
{CW_ELEM_CAPWAP_CONTROL_IPV4_ADDRESS, "Control IPv4 Address"},
{CW_ELEM_CAPWAP_CONTROL_IPV6_ADDRESS, "Control IPv6 Address"},
{CW_ELEM_CAPWAP_LOCAL_IPV4_ADDRESS, "CAWPAP Local IPv4 Address"},
{CW_ELEM_CAPWAP_LOCAL_IPV6_ADDRESS, "CAPWAP Local IPv6 Address"},
{CW_ELEM_CAPWAP_TIMERS, "CAPWAP Timers"},
{CW_ELEM_CAPWAP_TRANSPORT_PROTOCOL, "CAPWAP Transport Protocol"},
{CW_ELEM_DATA_TRANSFER_DATA, "Data Transfer Data"},
{CW_ELEM_DATA_TRANSFER_MODE, "Data Transfer Mode"},
{CW_ELEM_DECRYPTION_ERROR_REPORT, "Encryption Error Report"},
{CW_ELEM_DECRYPTION_ERROR_REPORT_PERIOD, "Decryption Error Report Period"},
{CW_ELEM_DELETE_MAC_ACL_ENTRY, "Delete MAC ACL Entry"},
{CW_ELEM_DELETE_STATION, "Delete Station"},
{CW_ELEM_RESERVED_19, "Reserved 19"},
{CW_ELEM_DISCOVERY_TYPE, "Discovery Type"},
{CW_ELEM_DUPLICATE_IPV4_ADDRESS, "Duplicate IPv4 Address"},
{CW_ELEM_DUPLICATE_IPV6_ADRESS, "Duplicate IPv6 Address"},
{CWMSGELEM_ECN_SUPPORT, "ECN Support"},
{CW_ELEM_IDLE_TIMEOUT, "Idle Timeout"},
{CW_ELEM_IMAGE_DATA, "Image Data"},
{CW_ELEM_IMAGE_IDENTIFIER, "Image Identifier"},
{CW_ELEM_IMAGE_INFORMATION, "Image Information"},
{CW_ELEM_INITIATE_DOWNLOAD, "Initiate Download"},
{CW_ELEM_LOCATION_DATA, "Location Data"},
{CW_ELEM_MAXIMUM_MESSAGE_LENGTH, "Maximum Message Length"},
{CWMSGELEM_MTU_DISCOVERY_PADDING, "MTU Discovery Padding"},
{CW_ELEM_RADIO_ADMINISTRATIVE_STATE, "Radio Administrative State"},
{CW_ELEM_RADIO_OPERATIONAL_STATE, "Radio Operational State"},
{CW_ELEM_RESULT_CODE, "Result Code"},
{CW_ELEM_RETURNED_MESSAGE_ELEMENT, "Returned Message Element"},
{CW_ELEM_SESSION_ID, "Session ID"},
{CW_ELEM_STATISTICS_TIMER, "Statistics Timer"},
{CW_ELEM_VENDOR_SPECIFIC_PAYLOAD, "Vendor Specific Payload"},
{CW_ELEM_WTP_BOARD_DATA, "WTP Board Data"},
{CW_ELEM_WTP_DESCRIPTOR, "WTP Descriptor"},
{CW_ELEM_WTP_FALLBACK, "WTP Fallback"},
{CW_ELEM_WTP_FRAME_TUNNEL_MODE, "WTP Frame Tunnel Mode"},
{CW_ELEM_RESERVED_42, "Reserved 42"},
{CW_ELEM_RESERVED_43, "Reserved 43"},
{CW_ELEM_WTP_MAC_TYPE, "WTP MAC Type"},
{CW_ELEM_WTP_NAME, "WTP Name"},
{CW_ELEM_RESERVED_46, "Reserved 46"},
{CW_ELEM_WTP_RADIO_STATISTICS, "WTP Radio Statistics"},
{CW_ELEM_WTP_REBOOT_STATISTICS, "WTP Reboot Statistics"},
{CW_ELEM_WTP_STATIC_IP_ADDRESS_INFORMATION, "WTP Static IP Address Information"},
/* Cisco's CAPWAP definitions (CAPWAP draft 7) */
/* CW_ELEM_WTP_IPV4_IP_ADDRESS 42
CW_ELEM_WTP_IPV6_IP_ADDRESS 43
*/
{CW_STR_STOP,"Unknown Element"}
};

View File

@ -0,0 +1,12 @@
#include "capwap_80211.h"
struct cw_strlist_elem capwap_strings_elem80211[] = {
{CW_ELEM80211_ADD_WLAN, "802.11 Add WLAN"},
{CW_ELEM80211_ANTENNA, "802.11 Antenna"},
{CW_ELEM80211_RATE_SET, " 802.11 Rate Set"},
{CW_ELEM80211_WTP_RADIO_INFORMATION, " 802.11 WTP Radio Information"},
{CW_STR_STOP, " Unknown "}
};

View File

@ -0,0 +1,9 @@
struct cw_str capwap_strings_item[] = {
{CW_ITEM_AC_DESCRIPTOR, "AC Descriptor"},
{CW_ITEM_AC_IPV4_LIST, "AC IPv4 List"},
{CW_ITEM_WTP_DESCRIPTOR,"WTP Descriptor"},
{CW_STR_STOP,"Unknown"}
}

View File

@ -0,0 +1,63 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Definition of CAPWAP Message Strings
*/
#include "capwap.h"
/**
* CAPWAP Message Strings
*/
struct cw_strlist_elem capwap_strings_msg[] = {
{ CW_MSG_DISCOVERY_REQUEST, "Discovery Request" },
{ CW_MSG_DISCOVERY_RESPONSE,"Discovery Response" },
{ CW_MSG_JOIN_REQUEST, "Join Request"},
{ CW_MSG_JOIN_RESPONSE,"Join Response"},
{ CW_MSG_CONFIGURATION_STATUS_REQUEST,"Configuration Status Request"},
{ CW_MSG_CONFIGURATION_STATUS_RESPONSE,"Configuration Status Response"},
{ CW_MSG_CONFIGURATION_UPDATE_REQUEST,"Configuration Update Request"},
{ CW_MSG_CONFIGURATION_UPDATE_RESPONSE,"Configuration Update Response"},
{ CW_MSG_WTP_EVENT_REQUEST,"WTP Event Request"},
{ CW_MSG_WTP_EVENT_RESPONSE,"WTP Event Response"},
{ CW_MSG_CHANGE_STATE_EVENT_REQUEST,"Change State Event Request"},
{ CW_MSG_CHANGE_STATE_EVENT_RESPONSE,"Change State Event Response"},
{ CW_MSG_ECHO_REQUEST,"Echo Request"},
{ CW_MSG_ECHO_RESPONSE,"Echo Response"},
{ CW_MSG_IMAGE_DATA_REQUEST,"Image Data Request"},
{ CW_MSG_IMAGE_DATA_RESPONSE,"Image Data Response"},
{ CW_MSG_RESET_REQUEST,"Reset Request"},
{ CW_MSG_RESET_RESPONSE,"Reset Response"},
{ CW_MSG_PRIMARY_DISCOVERY_REQUEST,"Primary Discovery Request"},
{ CW_MSG_PRIMARY_DISCOVERY_RESPONSE,"Primary Discovery Response"},
/* Data Transfer Request 21
Data Transfer Response 22
*/
{CW_MSG_CLEAR_CONFIGURATION_REQUEST,"Clear Configuration Request"},
{CW_MSG_CLEAR_CONFIGURATION_RESPONSE,"Clear Configuration Response"},
/* Station Configuration Request 25
Station Configuration Response 26
*/
{CW_STR_STOP,"Unknown Message Type"}
};

View File

@ -0,0 +1,17 @@
#include "capwap.h"
struct cw_strlist_elem capwap_strings_result[] = {
{CW_RESULT_SUCCESS,"Success"}, /* 0 */
{CW_RESULT_MISSING_AC_LIST,"AC List Message Element MUST be Present"}, /* 1 */
{CW_RESULT_SUCCESS_NAT,"Success - NAT Detected"}, /* 2 */
{CW_RESULT_RESET_UNABLE_TO_RESET,"Reset Failure - Unable to Reset"}, /* 10 */
{CW_RESULT_IMAGE_DATA_INVALID_CHECKSUM,"Image Data Error (Invalid Checksum)"}, /* 14 */
{CW_RESULT_IMAGE_DATA_ERROR,"Image Data Error (Unspecified)"}, /* 16 */
{CW_RESULT_MISSING_MAND_ELEM,"Missing Mandatory Message Element"}, /* 20 */
{CW_STR_STOP,"Unknown Result Code"}
};

View File

@ -0,0 +1,11 @@
#include "capwap.h"
struct cw_strlist_elem capwap_strings_state[] = {
{ CW_STATE_DISCOVERY, "Discovery" },
{ CW_STATE_JOIN,"Join" },
{ CW_STATE_RUN,"Run" },
{ CW_STATE_CONFIGURE,"Configure" },
{ CW_STATE_IMAGE_DATA,"Image Data" },
{ CW_STR_STOP,"Undefined" },
};

View File

@ -0,0 +1,11 @@
#include "capwap.h"
struct cw_strlist_elem capwap_strings_vendor[] = {
{ CW_VENDOR_ID_CISCO, "Cisco" },
{ CW_VENDOR_ID_ZYXEL, "Zyxel" },
{ CW_VENDOR_ID_FSF, "FSF"},
{ CW_VENDOR_ID_LANCOM, "Lancom"},
{ CW_VENDOR_ID_FORTINET, "Fortinet"},
{ CW_STR_STOP, "Unknown" }
};

14
src/cw/cipwap.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef __CIPWAP_H
#define __CIPWAP_H
#include "strheap.h"
#include "action.h"
extern struct cw_strlist_elem cipwap_strings_elem[];
extern int cw_register_actions_cipwap_wtp(struct cw_actiondef *def);
#endif

43
src/cw/cipwap_actions.h Normal file
View File

@ -0,0 +1,43 @@
#include "capwap_cisco.h"
#define CW_ACTION_IN_CISCO_AP_MODE_AND_TYPE \
CW_CISCO_AP_MODE_AND_TYPE, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_WORD, /* Type of element */ \
CW_ITEM_AP_MODE_AND_TYPE, /* ID to use store */ \
2, 2 /* min/max length */
#define CW_ACTION_IN_CISCO_RADIO_ADMINISTRATIVE_STATE \
CW_ELEM_RADIO_ADMINISTRATIVE_STATE, /* Element ID*/ \
cw_in_cisco_radio_administrative_state, 0, /* start/end callback */ \
MBAG_DWORD, /* Type of element */ \
0, /* ID to use store */ \
4, 4 /* min/max length */
#define CW_ACTION_IN_CISCO_RADIO_ADMINISTRATIVE_STATE_WTP \
CW_ELEM_RADIO_ADMINISTRATIVE_STATE, /* Element ID*/ \
cw_in_cisco_radio_administrative_state_wtp, 0, /* start/end callback */ \
MBAG_DWORD, /* Type of element */ \
0, /* ID to use store */ \
4, 4 /* min/max length */
#define CW_ACTION_IN_CISCO_RADIO_CFG\
CW_CISCO_WTP_RADIO_CFG, /* Element ID*/ \
cw_in_cisco_radio_cfg, 0, /* start/end callback */ \
NULL, /* Type of element */ \
0, /* ID to use store */ \
0, 1114 /* min/max length */
#define CW_ACTION_IN_CISCO_ADD_WLAN\
CW_CISCO_ADD_WLAN, /* Element ID*/ \
cw_in_cisco_add_wlan, 0, /* start/end callback */ \
NULL, /* Type of element */ \
0, /* ID to use store */ \
0, 1114 /* min/max length */

190
src/cw/cipwap_actions_ac.c Normal file
View File

@ -0,0 +1,190 @@
#include "capwap.h"
#include "capwap_cisco.h"
#include "capwap_actions.h"
#include "cipwap.h"
/**
*@file
*brief CIPWAP Actions
*/
#define CW_ACTION_IN_CISCO_IMAGE_IDENTIFIER \
CW_ELEM_IMAGE_IDENTIFIER, /* Element ID*/ \
cw_in_cisco_image_identifier, 0, /* start/end callback */ \
MBAG_VENDORSTR, /* Type of element */ \
CW_ITEM_IMAGE_IDENTIFIER, /* ID to use store */ \
1, 4096 /* min/max length */
#define CW_ACTION_IN_CIPWAP_WTP_DESCRIPTOR \
CW_ELEM_WTP_DESCRIPTOR, /* Element ID */ \
cw_in_cipwap_wtp_descriptor, 0, /* start/end callback */ \
0, \
CW_ITEM_WTP_DESCRIPTOR, \
8,1028
/* For CIPWAP we allow a
Session ID with 2 ... 16 bytes length */
#define CW_ACTION_IN_CIPWAP_SESSION_ID \
CW_ELEM_SESSION_ID, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_BSTR, /* Type of element */ \
CW_ITEM_SESSION_ID, /* ID to use store */ \
2, 16 /* min/max length */
#define CW_ACTION_IN_CIPWAP_AC_NAME \
CW_ELEM_AC_NAME, /* Element ID*/ \
cw_in_generic, 0, /* start/end callback */ \
MBAG_STR, /* Type of element */ \
CW_ITEM_AC_NAME, /* ID to use store */ \
0, 512 /* min/max length */
cw_action_in_t cipwap_actions_ac_in[] = {
/* -------------------------------------------------------------------------------
* Discovery Request IN
*/
{CW_VENDOR_ID_CISCO, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_REQUEST, CW_CISCO_RAD_NAME,
cw_in_generic, 0, MBAG_STR,CW_ITEM_WTP_NAME,1,512}
,
{CW_VENDOR_ID_CISCO, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST, CW_CISCO_AP_GROUP_NAME,
cw_in_generic, 0, MBAG_STR,CW_ITEM_WTP_GROUP_NAME,1,512}
,
{0, 0, CW_STATE_DISCOVERY, CW_MSG_DISCOVERY_REQUEST,
CW_ACTION_IN_CIPWAP_WTP_DESCRIPTOR,
1}
,
/* -------------------------------------------------------------------------------
* Join Request IN
*/
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST, 0,
0, cw_in_check_cipwap_join_req}
,
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST,
CW_ACTION_IN_CIPWAP_WTP_DESCRIPTOR, 1}
,
{0, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST,
CW_ACTION_IN_CIPWAP_SESSION_ID, 1}
,
/* -------------------------------------------------------------------------------
* Image Data Request - Conig State
*/
{0, 0, CW_STATE_CONFIGURE, CW_MSG_IMAGE_DATA_REQUEST,
CW_ACTION_IN_CISCO_IMAGE_IDENTIFIER,
0}
,
/* Element: Result Code
not mandatory in CIPWAP, while mandatory in CAPWAP
*/
{0, 0, CW_STATE_IMAGE_DATA, CW_MSG_IMAGE_DATA_RESPONSE,
CW_ACTION_IN_RESULT_CODE, 0}
,
/* ------------------------------------------------------------------------------- */
/* Message: Configuration Status Request */
/* Element: AC Name */
{0, 0, CW_STATE_CONFIGURE, CW_MSG_CONFIGURATION_STATUS_REQUEST,
CW_ACTION_IN_CIPWAP_AC_NAME, 1}
,
/* AP Mode and Type */
{CW_VENDOR_ID_CISCO, 0, CW_STATE_CONFIGURE, CW_MSG_CONFIGURATION_STATUS_REQUEST, CW_CISCO_AP_MODE_AND_TYPE,
cw_in_generic, 0, MBAG_WORD,CW_ITEM_AP_MODE_AND_TYPE,2,2}
,
{0,0,0}
};
extern struct cw_item *cw_get_local(struct conn *conn, struct cw_action_out *a);
cw_action_out_t cipwap_actions_ac_out[] = {
/* -------------------------------------------------------------------------------
* Discovery Response OUT
*/
/* AC Descriptor (Cisco) */
{CW_MSG_DISCOVERY_RESPONSE, CW_ITEM_AC_DESCRIPTOR, 0 ,
CW_ELEM_AC_DESCRIPTOR, NULL,cw_out_cisco_ac_descriptor, 0}
,
/* Cisco AP Timesync - Important to get the WTP a DTLS
connection established*/
{CW_MSG_DISCOVERY_RESPONSE, CW_ITEM_AC_TIMESTAMP, CW_VENDOR_ID_CISCO,
CW_CISCO_AP_TIMESYNC, NULL,cw_out_cisco_ap_timesync, 0}
,
/* -------------------------------------------------------------------------------
* Join Response OUT
*/
/* AC Descriptor (Cisco) */
{CW_MSG_JOIN_RESPONSE, CW_ITEM_AC_DESCRIPTOR, 0 ,
CW_ELEM_AC_DESCRIPTOR, NULL,cw_out_cisco_ac_descriptor, 0}
,
/* -------------------------------------------------------------------------------
* Echo Response OUT
*/
{CW_MSG_ECHO_RESPONSE, CW_ITEM_AC_TIMESTAMP, CW_VENDOR_ID_CISCO,
CW_CISCO_AP_TIMESYNC, NULL,cw_out_cisco_ap_timesync, 0}
,
/* --------------------------------------------------------------------------------
* Configuration Update Request
*/
{CW_MSG_CONFIGURATION_UPDATE_REQUEST, CW_ITEM_WTP_NAME, CW_VENDOR_ID_CISCO,
CW_CISCO_RAD_NAME, NULL,cw_out_generic, cw_out_get_outgoing,0}
,
{CW_MSG_CONFIGURATION_UPDATE_REQUEST, CW_ITEM_AP_MODE_AND_TYPE, CW_VENDOR_ID_CISCO,
CW_CISCO_AP_MODE_AND_TYPE, NULL,cw_out_generic, cw_out_get_outgoing,0}
,
{0,0,0}
};
/**
* Register CiPWAP actions
*/
int cw_register_actions_cipwap_ac(struct cw_actiondef *def)
{
int rc;
rc=cw_register_actions_capwap_ac(def);
rc+=cw_actionlist_in_register_actions(def->in, cipwap_actions_ac_in);
rc+=cw_actionlist_out_register_actions(def->out, cipwap_actions_ac_out);
rc+=cw_strheap_register_strings(def->strelem,cipwap_strings_elem);
return rc;
}

169
src/cw/cipwap_actions_wtp.c Normal file
View File

@ -0,0 +1,169 @@
/*
This file is part of libcipwap.
libcipwap 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.
libcipwap 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 <http://www.gnu.org/licenses/>.
*/
#include "cipwap.h"
#include "action.h"
#include "capwap_items.h"
#include "capwap_actions.h"
#include "capwap_cisco.h"
#include "strheap.h"
#include "cipwap_actions.h"
cw_action_in_t cipwap_actions_wtp_in[] = {
/* -------------------------------------------------------------------------------
* Configuration Update Request IN
*/
{CW_VENDOR_ID_CISCO, 0, CW_STATE_RUN, CW_MSG_CONFIGURATION_UPDATE_REQUEST, CW_CISCO_RAD_NAME,
cw_in_generic, 0, MBAG_BSTR16,CW_ITEM_WTP_NAME,0,512}
,
{CW_VENDOR_ID_CISCO, 0, CW_STATE_RUN, CW_MSG_CONFIGURATION_UPDATE_REQUEST, CW_CISCO_LOCATION_DATA,
cw_in_generic, 0, MBAG_BSTR16,CW_ITEM_LOCATION_DATA,0,512}
,
{CW_VENDOR_ID_CISCO, 0, CW_STATE_RUN, CW_MSG_CONFIGURATION_UPDATE_REQUEST, CW_CISCO_AC_NAME_WITH_INDEX,
cw_in_ac_name_with_priority, 0, MBAG_BSTR16,CW_ITEM_AC_NAME_WITH_PRIORITY,0,512}
,
/* AP Mode an Type IN */
/* {CW_VENDOR_ID_CISCO, 0, CW_STATE_RUN, CW_MSG_CONFIGURATION_UPDATE_REQUEST,
CW_ACTION_IN_CISCO_AP_MODE_AND_TYPE,
1}
,
*/
/* Radio Administrative State */
/* Overload CAPWAP action to handle a radio ID of 255 */
{0, 0, CW_STATE_RUN, CW_MSG_CONFIGURATION_UPDATE_REQUEST,
CW_ACTION_IN_CISCO_RADIO_ADMINISTRATIVE_STATE_WTP, 0}
,
/* Add WLAN */
{CW_VENDOR_ID_CISCO, 0, CW_STATE_RUN, CW_MSG_CONFIGURATION_UPDATE_REQUEST,
CW_ACTION_IN_CISCO_ADD_WLAN, 0}
,
{CW_VENDOR_ID_CISCO, 0, CW_STATE_JOIN, CW_MSG_JOIN_REQUEST, CW_CISCO_AP_GROUP_NAME,
cw_in_generic, 0, MBAG_BSTR16,CW_ITEM_WTP_GROUP_NAME,1,512}
,
/* -------------------------------------------------------------------------------
* Configuration Status Response IN
*/
{0, 0, CW_STATE_CONFIGURE, CW_MSG_CONFIGURATION_STATUS_RESPONSE,
CW_ACTION_IN_RADIO_ADMINISTRATIVE_STATE_WTP, 0}
,
{CW_VENDOR_ID_CISCO, 0, CW_STATE_CONFIGURE, CW_MSG_CONFIGURATION_STATUS_RESPONSE,
CW_ACTION_IN_CISCO_RADIO_CFG, 0}
,
{0, 0, 0}
};
cw_action_out_t cipwap_actions_wtp_out[] = {
/* -------------------------------------------------------------------------------
* Discovery Request OUT
*/
/* Cisco AP Groupname - Important to get the WTP a DTLS
connection established*/
{CW_MSG_DISCOVERY_REQUEST, CW_ITEM_WTP_GROUP_NAME, CW_VENDOR_ID_CISCO,
CW_CISCO_AP_GROUP_NAME, NULL,cw_out_generic, cw_out_get_config, 0}
,
/* -------------------------------------------------------------------------------
* Join Request OUT
*/
{CW_MSG_JOIN_REQUEST, CW_ITEM_CISCO_BOARD_DATA_OPTIONS, CW_VENDOR_ID_CISCO,
CW_CISCO_BOARD_DATA_OPTIONS, NULL,cw_out_generic, cw_out_get_config, 1}
,
/* -------------------------------------------------------------------------------
* Configuration Status Request OUT
*/
/* Cisco AP Groupname - Important to get the WTP a DTLS
connection established*/
{CW_MSG_CONFIGURATION_STATUS_REQUEST, CW_ITEM_RADIO_CFG, CW_VENDOR_ID_CISCO,
CW_CISCO_AP_GROUP_NAME, NULL,cw_out_cisco_wtp_radio_cfg, cw_out_get_config, 1}
,
{CW_MSG_CONFIGURATION_STATUS_REQUEST, CW_ITEM_AP_MODE_AND_TYPE, CW_VENDOR_ID_CISCO,
CW_CISCO_AP_MODE_AND_TYPE, NULL,cw_out_generic, cw_out_get_config, 1}
,
// {CW_MSG_DISCOVERY_REQUEST, CW_ITEM_NONE}
// ,
/* AC Name */
// {CW_MSG_DISCOVERY_REQUEST, CW_ITEM_DISCOVERY_TYPE, 0,
// CW_ELEM_DISCOVERY_TYPE, NULL,cw_out_generic, cw_out_get_outgoing}
/* -------------------------------------------------------------------------------
* Configuration Status Request OUT
*/
// {CW_MSG_CONFIGURATION_STATUS_REQUEST, CW_ITEM_NONE}
// ,
{0, 0}
};
int cw_register_actions_cipwap_wtp(struct cw_actiondef *def)
{
int rc;
rc=cw_register_actions_capwap_wtp(def);
rc+=cw_actionlist_in_register_actions(def->in, cipwap_actions_wtp_in);
rc+=cw_actionlist_out_register_actions(def->out, cipwap_actions_wtp_out);
rc += cw_strheap_register_strings(def->strelem, cipwap_strings_elem);
return rc;
}

View File

@ -0,0 +1,17 @@
#include "capwap.h"
#include "cipwap.h"
#include "capwap_cisco.h"
struct cw_strlist_elem cipwap_strings_elem[] = {
{CW_ELEM_WTP_IPV4_IP_ADDRESS, "WTP IPv4 IP Address"},
{CW_ELEM_WTP_IPV6_IP_ADDRESS, "WTP IPv6 IP Address"},
{CW_ELEM_AC_NAME_WITH_INDEX, "AC Name with Index"},
{CW_CISCO_AP_GROUP_NAME, "WTP Group Name" },
{CW_STR_STOP,"Unknown Element"}
};

171
src/cw/cisco.c Normal file
View File

@ -0,0 +1,171 @@
#include "capwap.h"
#include "capwap_cisco.h"
#include "mbag.h"
#include "radio.h"
#include "log.h"
#include "dbg.h"
int cw_put_cisco_wtp_radio_cfg(uint8_t *dst, int rid, mbag_t radio)
{
cw_put_byte(dst,rid);
cw_put_byte(dst+1,0); //?
cw_put_word(dst+2,mbag_get_word(radio,CW_RADIO_OCCUPANCY_LIMIT,12));
cw_put_byte(dst+4,mbag_get_byte(radio,CW_RADIO_CFP_PERIOD,8));
cw_put_word(dst+5,mbag_get_word(radio,CW_RADIO_CFP_MAX_DURATION,200));
bstr_t grmac = mbag_get_bstr(radio,CW_RADIO_BSSID,NULL);
//printf("GRMAC: %d\n",bstr_len(grmac));
if ( grmac) {
if (bstr_len(grmac)!=6){
cw_log(LOG_ERR,"Wrong bssid size");
exit(0);
grmac =NULL;
}
}
bstr_t rmac;
if (!grmac){
uint8_t defrmac[]={0,0,0,0,0,0};
rmac = bstr_create(defrmac,6);
}
else
rmac = grmac;
cw_put_bstr(dst+7,rmac);
if ( !grmac )
free(rmac);
cw_put_word(dst+13,0); // beacon period
cw_put_data(dst+15,mbag_get_raw(radio,CW_RADIO_COUNTRY_STRING,"DE "),3);
cw_put_data(dst+18,mbag_get_raw(radio,CW_RADIO_COUNTRY_STRING,"DE "),3);
cw_put_byte(dst+21,10); // gPeriod
cw_put_dword(dst+22,0x3538); // ?
cw_put_word(dst+26,0);
return 26+2; //+cw_put_elem_vendor_hdr(dst,CW_VENDOR_ID_CISCO,CW_CISCO_WTP_RADIO_CFG,28);
}
int cw_put_elem_cisco_ap_regulatory_domain(uint8_t *dst,int rid, mbag_t radio)
{
//int l=0;
uint8_t *d=dst+10;
d+=cw_put_byte(d,rid); /* Band ID */
d+=cw_put_byte(d,1); /* Set True/False */
d+=cw_put_byte(d,rid); /* Slot ID */
d+=cw_put_word(d,mbag_get_word(radio,CW_RADIO_REG_DOMAIN,1));
return 5 + cw_put_elem_vendor_hdr(dst, CW_VENDOR_ID_CISCO, CW_CISCO_AP_REGULATORY_DOMAIN, 5);
}
int cw_put_elem_cisco_radio_cfg(uint8_t * dst,int rid, mbag_t radio)
{
int l = cw_put_cisco_wtp_radio_cfg(dst+10,rid,radio);
return l+cw_put_elem_vendor_hdr(dst,CW_VENDOR_ID_CISCO,CW_CISCO_WTP_RADIO_CFG,l);
}
int cw_out_cisco_wtp_radio_cfg(struct conn *conn, struct cw_action_out *a, uint8_t * dst)
{
int l=0;
MAVLITER_DEFINE(it,conn->radios);
mavliter_foreach(&it){
struct mbag_item *i = mavliter_get(&it);
if ( i->type != MBAG_MBAG ) {
continue;
}
// l+=cw_put_elem_radio_info(dst+l,i->id,i->data);
l+=cw_put_elem_cisco_radio_cfg(dst+l,i->iid,i->data);
l+=cw_put_elem_cisco_ap_regulatory_domain(dst+l,i->iid,i->data);
}
return l;
// MAVLITER_DEFINE
// int l = cw_out_cisco_wtp_radio_cfg_(conn,a,dst,0);
// return l+cw_out_cisco_wtp_radio_cfg_(conn,a,dst+l,1);
}
int cw_in_cisco_radio_cfg(struct conn *conn, struct cw_action_in *a, uint8_t * data, int len,
struct sockaddr *from)
{
int rid = cw_get_byte(data);
mbag_t radio = mbag_i_get_mbag(conn->radios,rid,NULL);
if ( !radio){
cw_dbg(DBG_ELEM_ERR,"Radio ID %d not defined",rid);
return 0;
}
// printf("Here we are %d\n",rid);
return 0;
}
int cw_radio_cisco_set_state(struct conn * conn, uint8_t *data, int len, int cause)
{
int rid = cw_get_byte(data);
int state = cw_get_byte(data+1);
if (rid != 255)
return cw_radio_set_admin_state(conn->radios,rid,state,cause);
MAVLITER_DEFINE(it,conn->radios);
mavliter_foreach(&it){
mbag_item_t *i = mavliter_get(&it);
cw_radio_set_admin_state(conn->radios,i->iid,state,cause);
}
return 1;
}
int cw_in_cisco_radio_administrative_state(struct conn *conn, struct cw_action_in *a, uint8_t * data, int len,
struct sockaddr *from)
{
return cw_radio_cisco_set_state(conn,data,len,-1);
}
int cw_in_cisco_radio_administrative_state_wtp(struct conn *conn, struct cw_action_in *a, uint8_t * data, int len,
struct sockaddr *from)
{
return cw_radio_cisco_set_state(conn,data,len,3);
}

278
src/cw/conn.h Normal file
View File

@ -0,0 +1,278 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Connection object stuff
*/
#ifndef __CONN_H
#define __CONN_H
#include <stdint.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "fragman.h"
#include "cwmsg.h"
//#include "wtpinfo.h"
#include "action.h"
#include "mbag.h"
#include "intavltree.h"
#include "mbag.h"
#include "mod.h"
/**
* Connection Object
*/
struct conn {
int sock;
struct sockaddr_storage addr;
int recv_timeout;
mbag_t outgoing;
mbag_t incomming;
mbag_t remote;
mbag_t local;
mbag_t radios;
uint8_t radio_create;
mbag_t config;
/** base_mac */
bstr_t base_rmac;
/** Wireless Binding ID of this connection */
uint8_t wbid;
/** Counter for mandatory message elements */
struct avltree *mand;
/** Actionsdefs - this defines the possible actions for
this conn object, so in the end this is the specification
of the protocoll */
struct cw_actiondef *actions;
/** Current CAPWAP state */
uint8_t capwap_state;
/** The framgent manager used on this connection */
frag_t *fragman;
/** Current Fragment ID */
int fragid;
int seqnum;
int last_seqnum_received;
int last_message_id_received;
struct cwmsg req_msg;
struct cwmsg resp_msg;
/** Buffer for outgoing request messages */
uint8_t req_buffer[65536];
/** Buffer for outgoing response messages */
uint8_t resp_buffer[65536];
/** Max mtu, could be changed during discovery */
int mtu;
/* 0 mtu discovery turned off, 1 discovery tuned on */
int mtu_discovery;
/* receive and send methods */
int (*recv_packet) (struct conn *, uint8_t *, int);
int (*recv_packet_peek) (struct conn *, uint8_t *, int);
int (*send_packet) (struct conn *, const uint8_t *, int);
int (*readfrom) (struct conn *, uint8_t *, int, struct sockaddr_storage *);
int (*read) (struct conn *, uint8_t *, int);
int (*write) (struct conn *, const uint8_t *, int);
/* optional packet queue */
uint8_t **q;
int qsize;
int qrpos;
int qwpos;
sem_t q_sem;
uint8_t *cur_packet;
int cur_packet_len;
int cur_packet_pos;
/* dtls stuff */
int (*dtls_start) (struct conn *);
int (*dtls_accept) (struct conn *);
char *dtls_psk;
int dtls_psk_len;
char *dtls_cert_file;
char *dtls_key_file;
char *dtls_key_pass;
void *dtls_data;
char *dtls_cipher;
int dtls_error;
uint8_t dtls_cookie[8];
int dtls_verify_peer;
uint8_t dtls_buffer[2048];
int dtls_buffer_len;
int dtls_buffer_pos;
/* capwap timers */
int retransmit_interval;
int max_retransmit;
int wait_dtls;
int wait_join;
/* used to link the conn obj with other objects */
void *data;
/** Mode */
int capwap_mode;
/** CAWAP mode for outgoing messages */
int capwap_mode_out;
int strict_capwap;
int strict_hdr;
/*
int (*request_handler) (void *);
void *request_handler_param;
*/
int (*process_packet)(struct conn *conn, uint8_t * packet, int len,struct sockaddr *from);
int (*process_message)(struct conn *conn, uint8_t * rawmsg, int rawlen,
struct sockaddr *from);
int detected;
void * mods;
};
#define conn_is_strict_capwap(conn) (conn->strict_capwap)
struct conn *conn_create(int sock, struct sockaddr *addr, int qsize);
struct conn *conn_create_noq(int sock, struct sockaddr *addr);
extern int conn_send_cwmsg(struct conn *conn, struct cwmsg *cwmsg);
//extern int conn_process_packet(struct conn *conn, uint8_t * packet, int len,
// int (*cb) (void *, uint8_t *,int len), void *cbarg);
extern int conn_process_packet(struct conn *conn, uint8_t * packet, int len,struct sockaddr *from);
extern int process_message(struct conn *conn, uint8_t * rawmsg, int rawlen,
struct sockaddr *from);
extern uint8_t *conn_get_message(struct conn *conn);
extern int conn_send_packet(struct conn *conn, const uint8_t * buffer, int len);
extern void conn_destroy(struct conn *conn);
uint8_t *conn_q_get_packet(struct conn *conn);
extern int conn_q_recv_packet(struct conn *conn, uint8_t * buffer, int len);
extern int conn_q_recv_packet_peek(struct conn *conn, uint8_t * buffer, int len);
extern int conn_recv_packet(struct conn *conn, uint8_t * buf, int len);
extern int conn_recv_packet_peek(struct conn *conn, uint8_t * buf, int len);
extern int conn_send_response(struct conn *conn, struct cwmsg *cwmsg, int seqnum);
extern struct cwrmsg *conn_get_response(struct conn *conn);
#define conn_get_next_seqnum(conn) (conn->seqnum=((conn->seqnum+1)&0xff))
#define conn_get_last_seqnum(conn) (conn->seqnum&0xff)
/* connlist stuff */
#include "avltree.h"
struct connlist {
/* struct conn ** connlist; */
struct avltree *t;
int len;
pthread_mutex_t connlist_mutex;
};
struct connlist *connlist_create(int len);
void connlist_lock(struct connlist *cl);
void connlist_unlock(struct connlist *cl);
void conlist_destroy(struct connlist *cl);
struct conn *connlist_get(struct connlist *cl, const struct sockaddr *addr);
struct conn *connlist_add(struct connlist *cl, struct conn *conn);
void connlist_remove(struct connlist *cl, struct conn *conn);
void connlist_destroy(struct connlist *cl);
void conn_q_add_packet(struct conn *conn, uint8_t * packet, int len);
struct image_identifier;
struct cwimage_data;
extern void conn_prepare_request(struct conn *conn, int type);
extern int conn_prepare_image_data_request(struct conn *conn, struct cwimage_data *,
struct image_identifier *id);
//extern void conn_detect_capwap(struct conn *conn, struct wtpinfo *wtpinfo);
struct cwrmsg *conn_send_request(struct conn *conn);
struct cwrmsg *conn_wait_for_message(struct conn *conn, time_t timer);
struct cwrmsg *conn_wait_for_request(struct conn *conn, int *msglist, time_t timer);
#define conn_is_error(conn) (conn->dtls_error)
void conn_init(struct conn *conn);
extern int cw_read_messages(struct conn *conn);
extern int conn_recvfrom_packet(struct conn *conn, uint8_t * buf, int len,
struct sockaddr_storage *from);
int conn_send_msg(struct conn * conn, uint8_t *rawmsg);
int cw_read_from(struct conn * conn);
#endif /* __CONLIST_H */

102
src/cw/conn_create.c Normal file
View File

@ -0,0 +1,102 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "log.h"
#include "conn.h"
#include "sock.h"
#include "capwap.h"
/**
* Create a conn object
* @param sock a socket
* @param addr the address associated
* @param qsize size of packet queue
* @return A pointer to the created object
* This function creates a conn obnject with queueing functionality
* for asynchronous operation.
* To create a conn object without queue functionallity use #conn_create_noq.
*/
struct conn * conn_create(int sock, struct sockaddr * addr, int qsize)
{
struct conn * conn;
conn = malloc(sizeof (struct conn));
if (!conn)
return NULL;
conn_init(conn);
conn->sock=sock;
if (addr)
sock_copyaddr(&conn->addr,addr);
conn->fragman = fragman_create();
if (conn->fragman==NULL){
conn_destroy(conn);
return NULL;
}
conn->qsize=qsize;
if (qsize != 0){
if (!(conn->q=malloc( sizeof(uint8_t *) * qsize))){
conn_destroy(conn);
return NULL;
}
conn->qrpos=-1;
if (sem_init(&conn->q_sem,0,0)!=0){
cw_log(LOG_ERR,"Fatal- Can't init semaphore for conn object: %s",strerror(errno));
conn_destroy(conn);
return NULL;
};
conn->recv_packet=conn_q_recv_packet;
conn->recv_packet_peek=conn_q_recv_packet_peek;
}
else{
conn->recv_packet = conn_recv_packet;
conn->recv_packet_peek = conn_recv_packet_peek;
}
conn->send_packet = conn_send_packet;
conn->last_seqnum_received=-1;
conn->mtu=1500;
conn->cur_packet=0;
conn->recv_timeout=1;
conn->seqnum=-1;
conn->write = conn->send_packet;
conn->read = conn->recv_packet;
return conn;
}

82
src/cw/conn_create_noq.c Normal file
View File

@ -0,0 +1,82 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Implement conn_create_noq
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "conn.h"
#include "sock.h"
#include "log.h"
/**
* Create a connection object without queueing
* @retval 1 Success
* @retval 0 failure, conslt errno for more details
*/
struct conn * conn_create_noq(int sock, struct sockaddr * addr)
{
struct conn * conn;
conn = malloc(sizeof (struct conn));
if (!conn)
return NULL;
conn_init(conn);
conn->sock=sock;
if (addr)
sock_copyaddr(&conn->addr,addr);
/* create the CAPWAP framentation manager */
conn->fragman = fragman_create();
if (conn->fragman==NULL){
conn_destroy(conn);
return NULL;
}
/* set packet recieve and send methods */
conn->recv_packet = conn_recv_packet;
conn->recv_packet_peek = conn_recv_packet_peek;
conn->send_packet = conn_send_packet;
/* misc settings */
conn->last_seqnum_received=-1;
conn->mtu=1500;
conn->cur_packet=0;
conn->recv_timeout=1;
conn->seqnum=-1;
conn->write = conn->send_packet;
conn->read = conn->recv_packet;
return conn;
}

33
src/cw/conn_destroy.c Normal file
View File

@ -0,0 +1,33 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "conn.h"
void conn_destroy(struct conn * conn)
{
if (conn->fragman)
fragman_destroy(conn->fragman);
if (conn->q)
free (conn->q);
free(conn);
}

View File

@ -0,0 +1,35 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "capwap.h"
#include "wtpinfo.h"
#include "conn.h"
#include "log.h"
#include "sock.h"
void conn_detect_capwap(struct conn * conn, struct wtpinfo * wtpinfo)
{
if (wtpinfo->software_vendor_id == CW_VENDOR_ID_CISCO){
cw_dbg(DBG_CW_INFO,"Setting capwap mode *Cisco* on connection %s",sock_addr2str(&conn->addr));
conn->capwap_mode = CWMODE_CISCO;
return;
}
conn->capwap_mode = CWMODE_STD;
}

78
src/cw/conn_get_message.c Normal file
View File

@ -0,0 +1,78 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "conn.h"
#include "cwrmsg.h"
#include "cw_log.h"
#include "capwap.h"
#include "sock.h"
#include "cw_util.h"
struct args {
struct conn *conn;
struct cwrmsg *cwrmsg;
};
static int message_cb(void *p, uint8_t *rawmsg, int len)
{
struct args *args = (struct args *) p;
struct conn *conn = args->conn;
memcpy(conn->cwrmsg_buffer, rawmsg, len);
/*
memcpy(&conn->cwrmsg, cwrmsg, sizeof(struct cwrmsg));
conn->cwrmsg.msgelems = conn->cwrmsg_buffer;
*/
args->cwrmsg = &conn->cwrmsg;
return 0;
}
int conn_msg_processor(struct conn *conn)
{
uint8_t buf[2024];
int len = 2024;
int n = conn->read(conn, buf, len);
if (n<0 )
return n;
if (n > 0)
conn_process_packet(conn, buf, n, cw_process_msg, conn);
}
uint8_t *conn_get_message(struct conn *conn)
{
struct args args;
args.cwrmsg = 0;
args.conn = conn;
uint8_t buf[2024];
int len = 2024;
int n = conn->read(conn, buf, len);
if (n > 0)
conn_process_packet(conn, buf, n, message_cb, &args);
if (args.cwrmsg) {
cw_dbg(DBG_MSG,"Message recieved from %s",sock_addr2str(&conn->addr));
/*
cw_dbg(DBG_MSG,
"Received message from %s, type=%d - %s, seq=%d",
sock_addr2str(&conn->addr), args.cwrmsg->type,
cw_msgtostr(args.cwrmsg->type),
args.cwrmsg->seqnum);
*/
}
return conn->cwrmsg_buffer;
}

View File

@ -0,0 +1,44 @@
#include "capwap.h"
#include "cw_log.h"
#include "sock.h"
#include "cw_util.h"
struct cwrmsg * conn_get_response(struct conn * conn)
{
struct cwmsg * cwmsg = &conn->req_msg;
int type = cwmsg->type+1;
struct cwrmsg * cwrmsg;
int i;
for (i=0; i<conn->max_retransmit; i++) {
time_t r_timer = cw_timer_start(conn->retransmit_interval);
while(!cw_timer_timeout(r_timer)){
cwrmsg = conn_get_message(conn);
if (cwrmsg){
cw_dbg(DBG_MSG,"Received message from %s, type=%d - %s"
,sock_addr2str(&conn->addr),cwrmsg->type,cw_msgtostr(cwrmsg->type));
if (cwrmsg->type == type){
return cwrmsg;
}
}
if (conn->dtls_error)
return 0;
}
cw_dbg(DBG_MSG_ERR,"Retransmitting message, type=%d,seq=%d",cwmsg->type,cwmsg->seqnum);
conn_send_cwmsg(conn,&conn->req_msg);
}
cw_dbg(DBG_MSG_ERR,"Max retransmit's reached, message type=%d,seq=%d",cwmsg->type,cwmsg->seqnum);
return 0;
}

51
src/cw/conn_init.c Normal file
View File

@ -0,0 +1,51 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief conn_init
*/
#include <string.h>
#include "conn.h"
#include "capwap.h"
/**
* Basic initialization of a conn object
* @param conn conn object to initialize
*/
void conn_init(struct conn * conn)
{
memset(conn,0,sizeof(struct conn));
conn->retransmit_interval=CAPWAP_RETRANSMIT_INTERVAL;
conn->max_retransmit=CAPWAP_MAX_RETRANSMIT;
conn->wait_dtls=CAPWAP_WAIT_DTLS;
conn->wait_join=CAPWAP_WAIT_JOIN;
conn->mtu_discovery=1;
conn->capwap_mode = CW_MODE_AUTO;
conn->strict_capwap=1;
conn->remote = mbag_create();
conn->process_packet=conn_process_packet;
conn->process_message=process_message;
}

View File

@ -0,0 +1,12 @@
#include "conn.h"
#include "capwap.h"
void conn_prepare_configuration_update_request(struct conn * conn)
{
struct cwmsg * cwmsg = &conn->req_msg;
uint8_t * buffer = conn->req_buffer;
cwmsg_init(cwmsg,buffer,CW_MSG_CONFIGURATION_UPDATE_REQUEST,conn_get_next_seqnum(conn),0);
}

View File

@ -0,0 +1,59 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "capwap.h"
#include "lwapp.h"
int conn_prepare_image_data_request(struct conn *conn, struct cwimage_data *data,
struct image_identifier *id)
{
struct cwmsg *cwmsg = &conn->req_msg;
cwmsg_init(cwmsg, conn->req_buffer, CW_MSG_IMAGE_DATA_REQUEST, conn_get_next_seqnum(conn),
0);
if (!data)
return 0;
/* for Cisco APs send image data in "LWAPP format" */
if (conn->capwap_mode == CWMODE_CISCO) {
uint8_t type = 3;
uint16_t checksum = htons(lw_checksum(data->data, data->len));
cwmsg_vaddelem(cwmsg, CW_ELEM_IMAGE_DATA,
&type, 1,
&checksum, 2,
data->data, data->len,
NULL);
return 0;
}
/* standard capwap operation */
cwmsg_vaddelem(cwmsg,CW_ELEM_IMAGE_DATA,
&data->type, sizeof(data->type),
data->data, data->len,
NULL
);
return 0;
}

View File

@ -0,0 +1,10 @@
#include "conn.h"
#include "capwap.h"
void conn_prepare_request(struct conn * conn, int type)
{
struct cwmsg * cwmsg = &conn->req_msg;
uint8_t * buffer = conn->req_buffer;
cwmsg_init(cwmsg,buffer,type,conn_get_next_seqnum(conn),0);
cwmsg->capwap_mode=conn->capwap_mode;
}

View File

@ -0,0 +1,546 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "capwap.h"
#include "dbg.h"
#include "log.h"
#include "cw_util.h"
#include "conn.h"
#include "sock.h"
#include "stravltree.h"
int conn_send_msg(struct conn *conn, uint8_t * rawmsg);
/**
* Init response message header
*/
void cw_init_response(struct conn *conn, uint8_t * req)
{
uint8_t *buffer = conn->resp_buffer;
int shbytes = cw_get_hdr_msg_offset(req);
int dhbytes;
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);
uint8_t *msgptr = req + shbytes;
uint8_t *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 conn *conn, int msg_id)
{
uint8_t *buffer = conn->req_buffer;
/* zero the first 8 bytes */
cw_put_dword(buffer + 0, 0);
cw_put_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, 1);
cw_set_hdr_rid(buffer, 0);
uint8_t *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);
}
/**
* send a response
*/
int cw_send_response(struct conn *conn, uint8_t * rawmsg, int len)
{
cw_init_response(conn, rawmsg);
if (cw_put_msg(conn, conn->resp_buffer) == -1)
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
* @pqram result_code result code to send
* @return 1
*/
int cw_send_error_response(struct conn *conn, uint8_t * rawmsg, uint32_t result_code)
{
cw_init_response(conn, rawmsg);
uint8_t *out = conn->resp_buffer;
uint8_t *dst = cw_get_hdr_msg_elems_ptr(out);
int 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 int process_elements(struct conn *conn, uint8_t * rawmsg, int len,
struct sockaddr *from)
{
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), 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), 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), elems_len, payloadlen - 8);
elems_len = payloadlen - 8;
}
}
if (!conn->detected) {
if (conn->mods) {
struct mod_ac **mods = (struct mod_ac **) conn->mods;
int i;
for (i = 0; mods[i]; i++) {
if (mods[i]->detect) {
if (mods[i]->detect(conn, rawmsg, len, elems_len, from)) {
cw_dbg(DBG_INFO,
"Using mod '%s' to handle connection from %s",
mods[i]->name,
sock_addr2str(from));
break;
}
}
}
}
}
if (!conn->detected) {
cw_dbg(DBG_MSG_ERR, "Cant't detect capwap, discarding message from %s",
sock_addr2str(from));
// errno = EAGAIN;
// return -1;
}
/* prepare struct for search operation */
as.capwap_state = conn->capwap_state;
as.msg_id = cw_get_msg_id(msg_ptr);
as.vendor_id = 0;
as.elem_id = 0;
as.proto = 0;
/* Search for state/message combination */
afm = cw_actionlist_in_get(conn->actions->in, &as);
if (!afm) {
/* Throw away unexpected response messages */
if (!(as.msg_id & 1)) {
cw_dbg(DBG_MSG_ERR,
"Message type %d (%s) unexpected/illegal in %s State, discarding.",
as.msg_id, cw_strmsg(as.msg_id),
cw_strstate(conn->capwap_state));
errno = EAGAIN;
return -1;
}
/* Request message not found in current state, check if we know
anything else about this message type */
const char *str = cw_strheap_get(conn->actions->strmsg, as.msg_id);
int result_code = 0;
if (str) {
/* Message found, but it was in wrong state */
cw_dbg(DBG_MSG_ERR,
"Message type %d (%s) not allowed in %s State.", as.msg_id,
cw_strmsg(as.msg_id), cw_strstate(as.capwap_state));
result_code = CW_RESULT_MSG_INVALID_IN_CURRENT_STATE;
} else {
/* Message is unknown */
cw_dbg(DBG_MSG_ERR, "Message type %d (%s) unknown.",
as.msg_id, cw_strmsg(as.msg_id),
cw_strstate(as.capwap_state));
result_code = CW_RESULT_MSG_UNRECOGNIZED;
}
cw_send_error_response(conn, rawmsg, result_code);
errno = EAGAIN;
return -1;
}
/* 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);
uint8_t *elem;
/* Create an avltree to catch the found mandatory elements */
conn->mand = stravltree_create();
/* 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);
cw_dbg_elem(DBG_ELEM, conn, as.msg_id, as.elem_id, cw_get_elem_data(elem),
elem_len);
af = cw_actionlist_in_get(conn->actions->in, &as);
if (!af) {
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),
as.msg_id, cw_strmsg(as.msg_id));
continue;
}
int afrc = 1;
if (af->start) {
afrc =
af->start(conn, af, cw_get_elem_data(elem), elem_len, from);
}
if (af->mand && afrc) {
/* add found mandatory message element
to mand list */
stravltree_add(conn->mand, af->item_id);
}
}
/* all message elements are processed, do now after processing
by calling the "end" function for the message */
int result_code = 0;
if (afm->end) {
result_code = afm->end(conn, afm, rawmsg, len, from);
}
/* if we've got a request message, we always have to send a response message */
if (as.msg_id & 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) {
/* All 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.
*/
}
stravltree_destroy(conn->mand);
return result_code;
}
int process_message(struct conn *conn, uint8_t * rawmsg, int rawlen,
struct sockaddr *from)
{
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*/
uint8_t seqnum = cw_get_msg_seqnum(msgptr);
int s1 = conn->last_seqnum_received;
int s2 = seqnum;
int 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), 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), 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), 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_packet(struct 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);
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), len);
errno = EAGAIN;
return -1;
}
int 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), (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));
errno = EAGAIN;
return -1;
}
int offs = cw_get_hdr_msg_offset(packet);
int 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), 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), *(packet + 8));
errno = EAGAIN;
return -1;
}
}
if (cw_get_hdr_flag_f(packet)) {
/* fragmented, add the packet to fragman */
uint8_t *f;
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
int 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);
}
/**
* Used as main message loop
*/
int cw_read_messages(struct 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;
}
int cw_read_from(struct conn *conn)
{
if (!conn->readfrom) {
cw_log(LOG_ERR, "Fatal error, no readfrom method available.");
errno = EPROTO;
return -1;
}
uint8_t buf[2024];
int len = 2024;
struct sockaddr_storage from;
int n = conn->readfrom(conn, buf, len, &from);
if (n < 0)
return n;
if (n > 0) {
return conn->process_packet(conn, buf, n, (struct sockaddr *) &from);
}
errno = EAGAIN;
return -1;
}

View File

@ -0,0 +1,529 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "capwap.h"
#include "dbg.h"
#include "log.h"
#include "cw_util.h"
#include "conn.h"
#include "sock.h"
int conn_send_msg(struct conn *conn, uint8_t * rawmsg);
/**
* Init response message header
*/
void cw_init_response(struct conn *conn, uint8_t * req)
{
uint8_t *buffer = conn->resp_buffer;
int shbytes = cw_get_hdr_msg_offset(req);
int dhbytes;
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);
uint8_t *msgptr = req + shbytes;
uint8_t *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 conn *conn, int msg_id)
{
uint8_t *buffer = conn->req_buffer;
/* zero the first 8 bytes */
cw_put_dword(buffer + 0, 0);
cw_put_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, 1);
cw_set_hdr_rid(buffer, 0);
uint8_t *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);
}
/**
* send a response
*/
int cw_send_response(struct conn *conn, uint8_t * rawmsg, int len)
{
cw_init_response(conn, rawmsg);
if (cw_put_msg(conn, conn->resp_buffer) == -1)
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
* @pqram result_code result code to send
* @return 1
*/
int cw_send_error_response(struct conn *conn, uint8_t * rawmsg, uint32_t result_code)
{
cw_init_response(conn, rawmsg);
uint8_t *out = conn->resp_buffer;
uint8_t *dst = cw_get_hdr_msg_elems_ptr(out);
int 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 int process_elements(struct conn *conn, uint8_t * rawmsg, int len,
struct sockaddr *from)
{
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), 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), 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), elems_len, payloadlen - 8);
elems_len = payloadlen - 8;
}
}
if (!conn->detected) {
if (conn->mods){
struct mod_ac ** mods = (struct mod_ac **)conn->mods;
int i;
for (i=0; mods[i]; i++){
if (mods[i]->detect){
if (mods[i]->detect(conn,rawmsg,len,elems_len,from)){
cw_dbg(DBG_INFO,"Using mod '%s' to handle connection from %s",mods[i]->name,sock_addr2str(from));
break;
}
}
}
}
}
if (!conn->detected){
cw_dbg(DBG_INFO,"Cant't detect capwap, discarding message from %s",sock_addr2str(from));
errno=EAGAIN;
return -1;
}
/* prepare struct for search operation */
as.capwap_state = conn->capwap_state;
as.msg_id = cw_get_msg_id(msg_ptr);
as.vendor_id = 0;
as.elem_id = 0;
as.proto = 0;
/* Search for state/message combination */
afm = cw_actionlist_in_get(conn->actions->in, &as);
if (!afm) {
/* Throw away unexpected response messages */
if (!(as.msg_id & 1)) {
cw_dbg(DBG_MSG_ERR,
"Message type %d (%s) unexpected/illegal in %s State, discarding.",
as.msg_id, cw_strmsg(as.msg_id),
cw_strstate(conn->capwap_state));
errno = EAGAIN;
return -1;
}
/* Request message not found in current state, check if we know
anything else about this message type */
const char *str = cw_strheap_get(conn->actions->strmsg, as.msg_id);
int result_code = 0;
if (str) {
/* Message found, but it was in wrong state */
cw_dbg(DBG_MSG_ERR,
"Message type %d (%s) not allowed in %s State.", as.msg_id,
cw_strmsg(as.msg_id), cw_strstate(as.capwap_state));
result_code = CW_RESULT_MSG_INVALID_IN_CURRENT_STATE;
} else {
/* Message is unknown */
cw_dbg(DBG_MSG_ERR, "Message type %d (%s) unknown.",
as.msg_id, cw_strmsg(as.msg_id),
cw_strstate(as.capwap_state));
result_code = CW_RESULT_MSG_UNRECOGNIZED;
}
cw_send_error_response(conn, rawmsg, result_code);
errno = EAGAIN;
return -1;
}
/* 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);
uint8_t *elem;
/* Create an avltree to catch the found mandatory elements */
conn->mand = intavltree_create();
/* 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);
cw_dbg_elem(DBG_ELEM, conn, as.msg_id, as.elem_id, cw_get_elem_data(elem),
elem_len);
af = cw_actionlist_in_get(conn->actions->in, &as);
if (!af) {
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),
as.msg_id, cw_strmsg(as.msg_id));
continue;
}
int afrc = 1;
if (af->start) {
afrc =
af->start(conn, af, cw_get_elem_data(elem), elem_len, from);
}
if (af->mand && afrc) {
/* add found mandatory message element
to mand list */
intavltree_add(conn->mand, (int) af->item_id);
}
}
/* all message elements are processed, do now after processing
by calling the "end" function for the message */
int result_code = 0;
if (afm->end) {
result_code = afm->end(conn, afm, rawmsg, len, from);
}
/* if we've got a request message, we always have to send a response message */
if (as.msg_id & 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) {
/* All 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.
*/
}
intavltree_destroy(conn->mand);
return result_code;
}
int process_message(struct conn *conn, uint8_t * rawmsg, int rawlen,
struct sockaddr *from)
{
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*/
uint8_t seqnum = cw_get_msg_seqnum(msgptr);
int s1 = conn->last_seqnum_received;
int s2 = seqnum;
int 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), 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), 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), 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 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);
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), len);
errno = EAGAIN;
return -1;
}
int 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), (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));
errno = EAGAIN;
return -1;
}
int offs = cw_get_hdr_msg_offset(packet);
int 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), 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), *(packet + 8));
errno = EAGAIN;
return -1;
}
}
if (cw_get_hdr_flag_f(packet)) {
/* fragmented, add the packet to fragman */
uint8_t *f;
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
int 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);
}
/**
* Used as main message loop
*/
int cw_read_messages(struct 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;
}
int cw_read_from(struct conn *conn)
{
if (!conn->readfrom) {
cw_log(LOG_ERR, "Fatal error, no readfrom method available.");
errno = EPROTO;
return -1;
}
uint8_t buf[2024];
int len = 2024;
struct sockaddr_storage from;
int n = conn->readfrom(conn, buf, len, &from);
if (n < 0)
return n;
if (n > 0) {
return conn->process_packet(conn, buf, n, (struct sockaddr *) &from);
}
errno = EAGAIN;
return -1;
}

View File

@ -0,0 +1,52 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include "dbg.h"
#include "conn.h"
#include "sock.h"
void conn_q_add_packet(struct conn * conn,uint8_t *packet,int len)
{
int qwpos = conn->qwpos;
if (qwpos==conn->qsize)
qwpos=0;
if (conn->qrpos==qwpos){
/* no buffers, discard packet */
cw_dbg(DBG_PKT_ERR, "Discarding packet from %s, no queue buffers left",
sock_addr2str(&conn->addr));
return;
}
conn->q[qwpos]=malloc(len+4);
if (conn->q[qwpos]==NULL)
return;
*((uint32_t*)(conn->q[qwpos]))=len;
memcpy(conn->q[qwpos]+4,packet,len);
conn->qwpos=qwpos+1;
sem_post(&conn->q_sem);
}

View File

@ -0,0 +1,38 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <time.h>
#include "conn.h"
uint8_t * conn_q_get_packet(struct conn * conn)
{
struct timespec timespec;
clock_gettime(CLOCK_REALTIME,&timespec);
timespec.tv_sec++;
/* wait one second to get a packet */
if (sem_timedwait(&conn->q_sem,&timespec)==-1){
return NULL;
};
int qrpos = conn->qrpos+1;
if (qrpos==conn->qsize)
qrpos=0;
conn->qrpos=qrpos;
return conn->q[qrpos];
}

View File

@ -0,0 +1,71 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "conn.h"
static int conn_q_recv_packet_(struct conn * conn, uint8_t * buffer,int len,int peek)
{
if ( !conn->cur_packet)
{
if ((conn->cur_packet = conn_q_get_packet(conn)) == 0){
errno = EAGAIN;
return -1;
}
conn->cur_packet_len = *((uint32_t*)conn->cur_packet);
conn->cur_packet_pos=4;
}
if (conn->cur_packet_len > len )
{
memcpy(buffer,conn->cur_packet+conn->cur_packet_pos,len);
if (peek)
return len;
conn->cur_packet_pos+=len;
conn->cur_packet_len-=len;
if (conn->cur_packet_len==0){
free(conn->cur_packet);
conn->cur_packet=0;
}
return len;
}
memcpy(buffer,conn->cur_packet+conn->cur_packet_pos,conn->cur_packet_len);
if (peek)
return conn->cur_packet_len;
free (conn->cur_packet);
conn->cur_packet=0;
return conn->cur_packet_len;
}
int conn_q_recv_packet(struct conn * conn, uint8_t * buffer,int len)
{
return conn_q_recv_packet_(conn,buffer,len,0);
}
int conn_q_recv_packet_peek(struct conn * conn, uint8_t * buffer,int len)
{
return conn_q_recv_packet_(conn,buffer,len,1);
}

76
src/cw/conn_recv_packet.c Normal file
View File

@ -0,0 +1,76 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include "conn.h"
#include "sock.h"
int conn_recv_packet_(struct conn *conn, uint8_t * buf, int len, int flags)
{
int n;
while ((n = recv(conn->sock, (char *) buf, len, flags)) < 0) {
if (errno != EINTR) {
if (errno == EAGAIN)
return n;
}
}
return n;
}
int conn_recvfrom_packet(struct conn *conn, uint8_t * buf, int len,
struct sockaddr_storage *from)
{
socklen_t al;
al = sizeof(struct sockaddr_storage);
memset(from, 0, sizeof(struct sockaddr_storage));
int n;
while ((n = recvfrom(conn->sock, (char *) buf, len, 0, (struct sockaddr*)from, &al)) < 0) {
if (errno != EINTR) {
if (errno == EAGAIN)
return n;
}
}
return n;
}
/* yes, these functions could be better defined as macros in a .h file */
int conn_recv_packet(struct conn *conn, uint8_t * buf, int len)
{
return conn_recv_packet_(conn, buf, len, 0);
}
int conn_recv_packet_peek(struct conn *conn, uint8_t * buf, int len)
{
int rc = conn_recv_packet_(conn, buf, len, MSG_PEEK);
return rc;
}

107
src/cw/conn_send_msg.c Normal file
View File

@ -0,0 +1,107 @@
#include "conn.h"
#include "capwap.h"
#include "dbg.h"
#include "sock.h"
int conn_send_msg(struct conn * conn, uint8_t *rawmsg)
{
int packetlen = cw_get_hdr_msg_total_len(rawmsg);
cw_dbg_msg(DBG_MSG_OUT, conn,rawmsg, packetlen,(struct sockaddr*)&conn->addr);
//uint8_t * msgptr = rawmsg + cw_get_hdr_msg_offset(rawmsg);
/* Zyxel doesn't count msg element length from
behind seqnum */
if (conn->capwap_mode == CW_MODE_ZYXEL){
// XXX val-=3;
}
uint8_t * ptr = rawmsg;
int fragoffset = 0;
int hlen = cw_get_hdr_hlen(rawmsg)*4;
//cw_set_hdr_hlen(rawmsg,223);
//*(rawmsg + 8)=99;
//cw_set_hdr_flags(rawmsg,CW_FLAG_HDR_M,1);
int mtu = conn->mtu;
while (packetlen>mtu){
cw_set_hdr_flags(rawmsg,CW_FLAG_HDR_F,1);
cw_put_dword(ptr+4, conn->fragid<<16 | fragoffset<<3 );
cw_dbg_pkt(DBG_PKT_OUT,conn,ptr,mtu,(struct sockaddr*)&conn->addr);
//XXX
{
// char h[200];
// hdr_print(h,ptr,mtu);
// cw_dbg(DBG_PKT_OUT,"Sending capwap packet to %s:\n%s",sock_addr2str(&conn->addr),h);
}
// cw_dbg_dmp(DBG_PKT_DMP,ptr,mtu,"Sending packet ...");
if (conn->write(conn,ptr,mtu)<0)
return -1;
ptr +=mtu-hlen;
fragoffset+=(mtu-hlen)/8;
packetlen-=mtu-hlen;
//XXX if (hlen>8)
// memcpy(ptr+8,cwmsg->ctrlhdr+8,hlen-8);
}
// val = (preamble << 24) | ((hlen/4)<<19) | (cwmsg->rid<<14) |(wbid<<9) |
/*CWTH_FLAGS_T|*/ //cwmsg->flags;
//printf("VAL = %08x, %08x\n",val,cwmsg->flags);
//printf("FRag offset :::::::::::::::::::::::::::: %d\n",fragoffset);
if (fragoffset)
cw_set_hdr_flags(rawmsg,CW_FLAG_HDR_F | CW_FLAG_HDR_L,1);
else
cw_set_hdr_flags(rawmsg,CW_FLAG_HDR_F,0);
// printf("Setting first byte %08X\n",val);
// *((uint32_t*)ptr)=htonl(val);
// val = conn->fragid<<16 | fragoffset<<3;
// *((uint32_t*)(ptr+4))=htonl(val);
cw_put_dword(ptr+4, conn->fragid<<16 | fragoffset<<3 );
{
// char h[1024];
// hdr_print(h,ptr,msglen-fragoffset*8+hlen);
// cw_dbg(DBG_CW_PKT_OUT,"Sending capwap packet to %s:\n%s",sock_addr2str(&conn->addr),h);
}
// cw_dbg_dmp(DBG_PKT_DMP,ptr,packetlen,"Sending packet ...");
//return conn->write(conn,ptr,msglen-fragoffset*8+hlen);
//printf("Send packet len %p %d\n",ptr,packetlen);
cw_dbg_pkt(DBG_PKT_OUT,conn,ptr,packetlen,(struct sockaddr*)&conn->addr);
return conn->write(conn,ptr,packetlen-0);
}

50
src/cw/conn_send_packet.c Normal file
View File

@ -0,0 +1,50 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <sys/socket.h>
#include "sock.h"
#include "conn.h"
#include <netinet/in.h>
#include <arpa/inet.h>
int conn_send_packet(struct conn * conn, const uint8_t * buffer, int len)
{
/*
#ifdef WITH_CW_LOG_DEBUG
char addrstr[64];
sock_addrtostr((struct sockaddr*)&conn->addr,addrstr,64);
cw_log_debug1("Sending packet to %s, len=%d",addrstr,len);
cw_log_debug2_dump(buffer,len,"Packet data for packet, sent to %s",addrstr);
#endif
*/
int n;
while((n=sendto( conn->sock, buffer, len, 0,
(struct sockaddr*)&conn->addr,
sock_addrlen((struct sockaddr*)&conn->addr)))<0 ){
if(errno == EINTR)
continue;
return n;
}
return n;
}

View File

@ -0,0 +1,61 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
*@file
*@brief conn_send_request
*/
#include "capwap.h"
#include "cw_util.h"
#include "cw_log.h"
/**
* Send a request message and wait for its response
* @param conn the connection
*
* The message has to be prepared and put to conn->req_msg
*
*/
struct cwrmsg * conn_send_request(struct conn * conn)
{
int i;
struct cwrmsg * cwrmsg;
struct cwmsg * cwmsg = &conn->req_msg;
for (i=0; i<conn->max_retransmit; i++) {
time_t r_timer = cw_timer_start(conn->retransmit_interval);
if (i!=0)
cw_dbg(DBG_MSG_ERR,"Retransmitting message, type=%d,seq=%d",cwmsg->type,cwmsg->seqnum);
conn_send_cwmsg(conn,&conn->req_msg);
cwrmsg = conn_wait_for_message(conn,r_timer);
if (cwrmsg){
if (cwrmsg->type == conn->req_msg.type+1){
return cwrmsg;
}
}
}
cw_dbg(DBG_MSG_ERR,"Max retransmit's reached, message type=%d,seq=%d",cwmsg->type,cwmsg->seqnum);
return 0;
}

View File

@ -0,0 +1,37 @@
#include "conn.h"
#include "cw_util.h"
struct cwrmsg * conn_wait_for_message(struct conn * conn, time_t timer)
{
struct cwrmsg * cwrmsg;
while (!cw_timer_timeout(timer)){
cwrmsg = conn_get_message(conn);
if (!cwrmsg){
if (!conn_is_error(conn))
continue;
return 0;
}
if (cwrmsg->type & 1){
if (conn->request_handler){
if (conn->request_handler(conn->request_handler_param))
continue;
}
}
return cwrmsg;
}
return 0;
}

View File

@ -0,0 +1,78 @@
#include "conn.h"
#include "cw_log.h"
#include "sock.h"
#include "cw_util.h"
struct rh_param{
struct conn * conn;
int *msglist;
};
static int conn_rh(void *param)
{
struct rh_param * p = (struct rh_param*)param;
int i;
int *msglist=p->msglist;
printf("Param %p\n",param);
for (i=0; msglist[i]!=-1; i++){
if (msglist[i] == p->conn->cwrmsg.type )
return 0;
}
/* unexpected response here */
cw_log(LOG_ERR,"Unexpected message from %s",sock_addr2str(&p->conn->addr));
cwsend_unknown_response(p->conn,p->conn->cwrmsg.seqnum,p->conn->cwrmsg.type);
return 1;
}
struct cwrmsg * conn_wait_for_request(struct conn * conn, int *msglist, time_t timer)
{
int (*request_handler_save) (void*);
void * request_handler_param_save;
struct rh_param rh_param;
if (msglist){
request_handler_save=conn->request_handler;
request_handler_param_save=conn->request_handler_param;
rh_param.conn=conn;
rh_param.msglist=msglist;
conn->request_handler=conn_rh;
conn->request_handler_param=&rh_param;
}
struct cwrmsg * cwrmsg;
while (!cw_timer_timeout(timer)){
cwrmsg = conn_wait_for_message(conn,timer);
if (!cwrmsg){
if (!conn_is_error(conn))
continue;
break;
}
/* response message? no action*/
if (! (cwrmsg->type & 1) )
continue;
/* it's a request message */
break;
}
if (msglist){
conn->request_handler=request_handler_save;
conn->request_handler_param=request_handler_param_save;
}
return cwrmsg;
}

101
src/cw/connlist.c Normal file
View File

@ -0,0 +1,101 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include "conn.h"
#include "sock.h"
static int connlist_cmp(const void * d1,const void *d2)
{
struct conn * c1=(struct conn *) d1;
struct conn * c2=(struct conn *) d2;
return sock_cmpaddr((struct sockaddr*)&c1->addr,(struct sockaddr*)&c2->addr,1);
}
struct connlist * connlist_create(int len)
{
struct connlist * cl = malloc(sizeof(struct connlist));
if (!cl)
return 0;
cl->t = avltree_create(connlist_cmp,0);
if (!cl->t){
free(cl);
return 0;
}
if (pthread_mutex_init(&cl->connlist_mutex,NULL)){
avltree_destroy(cl->t);
free(cl);
return 0;
};
cl->len=len;
return cl;
}
void connlist_lock(struct connlist * cl)
{
pthread_mutex_lock(&cl->connlist_mutex);
}
void connlist_unlock(struct connlist * cl)
{
pthread_mutex_unlock(&cl->connlist_mutex);
}
void connlist_destroy(struct connlist * cl)
{
if (!cl)
return;
if (cl->t)
avltree_destroy(cl->t);
pthread_mutex_destroy(&cl->connlist_mutex);
free(cl);
}
struct conn * connlist_get(struct connlist * cl, const struct sockaddr * addr)
{
struct conn dummy;
sock_copyaddr(&dummy.addr,addr);
return avltree_get(cl->t,&dummy);
}
struct conn * connlist_add(struct connlist * cl, struct conn * conn)
{
if ( cl->len!=0)
if (cl->t->count>=cl->len)
return 0;
return avltree_add(cl->t,conn);
}
void connlist_remove(struct connlist *cl,struct conn * conn)
{
avltree_del(cl->t,conn);
}

19
src/cw/cw.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef __CW_H
#define __CW_H
#include "mbag.h"
#include "conn.h"
#include "action.h"
extern int cw_read_wtp_descriptor(mbag_t mbag, struct conn *conn,
struct cw_action_in *a, uint8_t * data, int len);
extern int cw_read_wtp_descriptor_7(mbag_t mbag, struct conn *conn,
struct cw_action_in *a, uint8_t * data, int len);
extern int cw_read_wtp_descriptor_versions(mbag_t mbag, uint8_t * data,
int len);
#endif

View File

@ -0,0 +1,79 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "capwap.h"
#include "cwmsg.h"
#include "conn.h"
uint8_t * cw_addelem(uint8_t * buf,int type, uint8_t *elem, int len)
{
uint32_t val = type<<16|len;
*((uint32_t*)(buf))=htonl(val);
buf+=4;
memcpy(buf,elem,len);
return buf+len;
}
void cw_addelem_capwap_local_ip_addr(struct cwmsg *msg, int sock, int cw_mode)
{
struct sockaddr_storage a;
socklen_t alen = sizeof(struct sockaddr_storage);
getsockname (sock,(struct sockaddr *)&a,&alen);
int cw_mode = cwmsg->capwap_mode;
switch (((struct sockaddr*)&a)->sa_family){
case AF_INET:
{
struct sockaddr_in * sain = (struct sockaddr_in*)&a;
int id;
if (cw_mode == CWMODE_CISCO)
id = CWMSGELEM_WTP_IPV4_IP_ADDR;
else
id = CWMSGELEM_CAPWAP_LOCAL_IPV4_ADDRESS;
cwmsg_addelem(msg,id,(uint8_t*)&sain->sin_addr,4);
break;
}
case AF_INET6:
{
int id;
if (cw_mode == CWMODE_CISCO)
id = CWMSGELEM_WTP_IPV6_IP_ADDR;
else
id = CWMSGELEM_CAPWAP_LOCAL_IPV6_ADDRESS;
struct sockaddr_in6 * sain = (struct sockaddr_in6*)&a;
return cwmsg_addelem(msg,id,(uint8_t*)&sain->sin6_addr,16);
}
break;
}
}

View File

@ -0,0 +1,26 @@
#include "capwap.h"
#include "capwap_cisco.h"
int cw_addelem_cisco_wtp_radio_cfg(uint8_t*dst,struct radioinfo *ri)
{
cw_put_byte(dst+10,ri->rid);
cw_put_byte(dst+10+1,0);
cw_put_word(dst+10+2,ri->occupancy_limit);
cw_put_byte(dst+10+4,ri->cfp_period);
cw_put_word(dst+10+5,ri->cfp_max_duration);
/* XXX catch rmac shorter or longer than 6*/
cw_put_bstr(dst+10+7,ri->rmac); /* length MUST be 6 */
cw_put_word(dst+10+13,ri->beacon_period);
cw_put_data(dst+10+15,ri->country_str,3);
cw_put_data(dst+10+18,ri->country_str2,3);
cw_put_byte(dst+10+21,10); // gPeriod
cw_put_dword(dst+10+22,0x3538); // ?
return 28+cw_put_elem_vendor_hdr(dst,CW_VENDOR_ID_CISCO,CW_CISCO_WTP_RADIO_CFG,28);
}

View File

@ -0,0 +1,48 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
*@file
*@brief cw_addelem_vendor_specific_payload
*/
#include "capwap.h"
/**
* Add a Vendor Specific Payload message element to a buffer
* @param dst destination buffer
* @param vendor_id the vendor id
* @param type vendor specific message type
* @data pointer to data the will be put
* @len length of data
*/
int cw_addelem_vendor_specific_payload(uint8_t * dst, uint32_t vendor_id,
uint16_t type, uint8_t * data, uint16_t len)
{
uint8_t *d = dst + 4;
d += cw_put_dword(d, vendor_id);
d += cw_put_word(d, type);
d += cw_put_data(d, data, len);
int l = d - dst;
cw_put_elem_hdr(dst, CW_ELEM_VENDOR_SPECIFIC_PAYLOAD, l - 4);
return l;
}

View File

@ -0,0 +1,36 @@
#include "capwap.h"
#include "dbg.h"
int cw_check_missing_mand(cw_action_in_t ** out, struct conn * conn, cw_action_in_t *a)
{
cw_action_in_t as;
as.capwap_state = a->capwap_state;
as.msg_id = a->msg_id;
as.vendor_id = 0;
as.elem_id = 0;
as.proto=0;
DEFINE_AVLITER(it,conn->actions->in);
int n=0;
avliter_foreach_from(&it,&as) {
cw_action_in_t * ai = avliter_get(&it);
if (ai->msg_id != as.msg_id && ai->capwap_state != as.capwap_state)
break;
if (!ai->mand)
continue;
void * rc = mavl_get(conn->mand,(void*)ai->item_id);
if (!rc) {
out[n++]=ai;
}
}
return n;
}

145
src/cw/cw_cisco_id_to_str.c Normal file
View File

@ -0,0 +1,145 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Implements cw_cisco_id_to_str
*/
#include "capwap_cisco.h"
/**
* Get a text representation of a Cisco vendor specific message element
* @param elem_id vendor specific message element
* @return pointer printable string
*/
const char * cw_cisco_id_to_str(int elem_id)
{
switch (elem_id) {
case CW_CISCO_AP_GROUP_NAME:
return "AP Group Name";
case CW_CISCO_RAD_NAME:
return "RAD Name";
case CW_CISCO_AP_TIMESYNC:
return "AP Timesync";
case CW_CISCO_MWAR_TYPE:
return "MWAR Type";
case CW_CISCO_SPAM_VENDOR_SPECIFIC:
return "LWAPP Vendor Specific";
case CW_CISCO_WTP_RADIO_CFG:
return "WTP Radio CFG";
case CW_CISCO_AP_REGULATORY_DOMAIN:
return "AP Regulatory Domain";
case CW_CISCO_WTP_BOARD_DATA:
return "WTP Board Data";
case CW_CISCO_MULTI_DOMAIN_CAPAB:
return "Multi Domain Capability";
case CW_CISCO_AP_STATIC_IP_ADDR:
return "AP Static IP Addr";
case CW_CISCO_AP_DOMAIN:
return "AP Domain";
case CW_CISCO_AP_DNS:
return "AP DNS";
case CW_CISCO_AC_NAME_WITH_INDEX:
return "AC Name with Index";
case CW_CISCO_AC_IPV4_LIST:
return "AC IPv4 List";
case CW_CISCO_LOCATION_DATA:
return "Location Data";
case CW_CISCO_STATISTICS_TIMER:
return "Statistics Timer";
case CW_CISCO_AP_MODE_AND_TYPE:
return "AP Mode and Type";
case CW_CISCO_ADD_WLAN:
return "Add WLAN";
case CW_CISCO_MWAR_ADDR:
return "MWAR Addr";
case CW_CISCO_BOARD_DATA_OPTIONS:
return "WTP Board Data Options";
case CW_CISCO_AP_RESET_BUTTON_STATE:
return "Reset Button State";
case CW_CISCO_MAC_OPERATION:
return "Mac Operation";
case CW_CISCO_TX_POWER:
return "TX Power";
case CW_CISCO_TX_POWER_LEVELS:
return "TX Power Levels";
case CW_CISCO_DIRECT_SEQUENCE_CONTROL:
return "Direct Sequence Control";
case CW_CISCO_AP_MODEL:
return "AP Model";
case CW_CISCO_AP_MINIOS_VERSION:
return "AP MiniOS Version";
case CW_CISCO_LWAPP_CHANNEL_POWER:
return "LWAPP Channel Power";
case CW_CISCO_ANTENNA_PAYLOAD:
return "Antenna Payload";
case CW_CISCO_SUPPORTED_RATES:
return "Supported Rates";
case CW_CISCO_SPAM_DOMAIN_SECRET:
return "SPAM Domain Secret";
case CW_CISCO_SPAM_AP_LED_STATE:
return "SPAM AP LED State";
case CW_CISCO_AP_RETRANSMIT_PARAM:
return "AP Retransmit Param";
case CW_CISCO_AP_VENUE_SETTINGS:
return "AP Venue Settings";
case CW_CISCO_80211_DELETE_WLAN:
return "Delete WLAN";
case CW_CISCO_SIG_PAYLOAD:
return "Signature Payload";
case CW_CISCO_SIG_TOGGLE:
return "Signature Toggle";
case CW_CISCO_80211_ASSOC_LIMIT:
return "Assoc Limit";
case CW_CISCO_AP_QOS:
return "AP Quality of Services";
case CW_CISCO_TLV_PAYLOAD:
return "TLV Payload";
case CW_CISCO_AP_UPTIME:
return "AP Uptime";
case CW_CISCO_AP_POWER_INJECTOR_CONFIG:
return "AP Power Injector Config";
case CW_CISCO_AP_PRE_STD_SWITCH_CONFIG:
return "AP Pre Std Switch Config";
case CW_CISCO_AP_BACKUP_SOFTWARE_VERSION:
return "Backup Software Version";
case CW_CISCO_AP_LOG_FACILITY:
return "AP Log Facility";
default:
return "Unknown";
}
}

23
src/cw/cw_get_mod_ac.c Normal file
View File

@ -0,0 +1,23 @@
#include <string.h>
#include "mod.h"
#include <stdio.h>
struct mod_ac *(*mods_ac[])() = MODS_AC;
struct mod_ac * cw_get_mod_ac(const char *name)
{
int i;
for (i=0; mods_ac[i];i++){
struct mod_ac * m = mods_ac[i]();
if (strcmp(m->name,name)==0)
return m;
}
return NULL;
}

View File

@ -0,0 +1,130 @@
#include "capwap.h"
#include "capwap_items.h"
#include "dbg.h"
#include "mbag.h"
/*
static int read_subelem_cisco(struct ac_info* acinfo,int subtype,uint8_t * elem, int len)
{
switch (subtype) {
case 0:
bstr_replace(&acinfo->hardware_version,bstr_create(elem,len));
break;
case 1:
bstr_replace(&acinfo->software_version,bstr_create(elem,len));
break;
default:
//printf("What? %d\n",subtype);
break;
}
return 1;
}
*/
/*
static int read_subelem(struct ac_info* acinfo,int subtype,uint8_t *elem, int len)
{
switch (subtype){
case 0:
case 4:
bstr_replace(&acinfo->hardware_version,bstr_create(elem,len));
break;
case 1:
case 5:
bstr_replace(&acinfo->software_version,bstr_create(elem,len));
break;
}
return 1;
}
*/
static int read_subeelms(struct conn *conn,struct cw_action_in * a,uint8_t *data,int len,struct sockaddr *from)
{
int sub=12;
//int sublen;
while (sub<len){
if (len-sub<8)
return 0;
uint32_t vendor_id = cw_get_dword(data+sub);
int sublen = cw_get_word(data+sub+6);
int subtype = cw_get_word(data+sub+4);
printf("substart : %d\n",sub);
vendorstr_t vstr=NULL;
switch (subtype){
case 0:
case 4:
/* hardware version */
vstr = mbag_set_vendorstr(conn->incomming,CW_ITEM_AC_HARDWARE_VERSION,
vendor_id,data+sub+8,sublen);
break;
case 1:
case 5:
/* software version */
vstr = mbag_set_vendorstr(conn->incomming,CW_ITEM_AC_SOFTWARE_VERSION,
vendor_id,data+sub+8,sublen);
break;
}
cw_dbg_version_subelem(DBG_SUBELEM,"AC Descriptor", subtype, vstr);
if (sub+sublen>len)
return -1;
sub+=sublen+8;
}
return 1;
}
int cw_in_ac_descriptor(struct conn *conn,struct cw_action_in * a,uint8_t *data,int len,struct sockaddr *from)
{
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 Desriptor: 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);
read_subeelms(conn,a,data,len,from);
return 1;
}

View File

@ -0,0 +1,30 @@
#include "action.h"
#include "dbg.h"
#include "log.h"
#include "mbag.h"
#include "capwap.h"
#include "acpriolist.h"
#include "capwap_items.h"
int cw_in_ac_name_with_priority(struct conn *conn, struct cw_action_in *a, uint8_t * data, int len,
struct sockaddr *from)
{
cw_acpriolist_t prios = mbag_get_mavl(conn->config,CW_ITEM_AC_NAME_WITH_PRIORITY);
if (!prios)
return 0;
cw_acprio_t * prio = malloc(sizeof(cw_acprio_t));
if (!prio)
return 0;
prio->prio=cw_get_byte(data);
prio->name=strndup((char*)data+1,len-1);
mavl_replace(prios,prio);
return 1;
}

View File

@ -0,0 +1,50 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include "action.h"
#include "log.h"
#include "mbag.h"
#include "capwap.h"
#include "capwap_items.h"
#include "aciplist.h"
#include "sock.h"
int cw_in_capwap_control_ipv4_address(struct conn *conn, struct cw_action_in *a,
uint8_t * data, int len,struct sockaddr *from)
{
cw_aciplist_t list =
mbag_get_mavl_c(conn->incomming,a->item_id,cw_aciplist_create);
if (!list) {
cw_log(LOG_ERR, "Error: Can't allocate CAWAP IP Adress List");
return 0;
}
cw_acip_t * acip;
acip = malloc(sizeof(cw_acip_t));
if (!acip) {
cw_log(LOG_ERR,"Can't allocate memory for acv4ip: %s",strerror(errno));
return 0;
}
struct sockaddr_in addr;
memcpy(&addr.sin_addr,data,4);
addr.sin_family=AF_INET;
sock_setport((struct sockaddr*)&addr,CAPWAP_CONTROL_PORT);
memcpy(&acip->ip,&addr,sizeof(addr));
acip->wtp_count = cw_get_word(data+4);
cw_aciplist_replace(list,acip);
return 1;
}

View File

@ -0,0 +1,31 @@
#include "capwap.h"
#include "intavltree.h"
#include "dbg.h"
#include "log.h"
#include "capwap_items.h"
int cw_in_check_cfg_update_req(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len,struct sockaddr *from)
{
cw_action_in_t * mlist[60];
/* Check for mandatory elements */
int n = cw_check_missing_mand(mlist,conn,a);
if (n) {
if ( conn->strict_capwap ){
cw_dbg_missing_mand(DBG_MSG_ERR,conn,mlist,n,a);
conn->capwap_state=CW_STATE_JOIN;
return CW_RESULT_MISSING_MAND_ELEM;
}
cw_dbg_missing_mand(DBG_RFC,conn,mlist,n,a);
}
/* set result code to ok and change to configure state */
mbag_set_dword(conn->outgoing,CW_ITEM_RESULT_CODE,0);
return 0;
}

View File

@ -0,0 +1,13 @@
#include "capwap.h"
#include "intavltree.h"
#include "dbg.h"
#include "log.h"
#include "capwap_items.h"
int cw_in_check_chng_state_evnt_req(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len,struct sockaddr *from)
{
conn->capwap_state = CW_STATE_RUN;
return 0;
}

View File

@ -0,0 +1,62 @@
#include "capwap.h"
#include "intavltree.h"
#include "dbg.h"
#include "log.h"
#include "capwap_items.h"
#include "bstr.h"
#include "sock.h" //tube
void cw_get_wtp_name(struct conn *conn,struct sockaddr *addr)
{
}
int cw_set_capwap_mode(struct conn *conn,int mode)
{
cw_dbg(DBG_INFO,"Setting CAPWAP mode to %d for %s",mode,sock_addr2str(&conn->addr));
conn->capwap_mode_out=mode;
return 1;
}
int cw_detect_capwap(struct conn *conn)
{
mbag_t is = conn->incomming;
mbag_item_t * item = mbag_get(is,CW_ITEM_WTP_SOFTWARE_VERSION);
if (item) {
vendorstr_t s = item->data;
uint32_t v = vendorstr_get_vendor_id(s);
switch(v) {
case CW_VENDOR_ID_CISCO:
cw_set_capwap_mode(conn,CW_MODE_CISCO);
break;
default:
cw_set_capwap_mode(conn,CW_MODE_CAPWAP);
break;
}
}
return 0;
}
int cw_in_check_cipwap_join_req(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len,struct sockaddr *from)
{
int rc = cw_in_check_join_req(conn,a,data,len,from);
if ( rc==0 ) {
cw_detect_capwap(conn);
}
return rc;
}

View File

@ -0,0 +1,40 @@
#include "capwap.h"
#include "capwap_items.h"
#include "intavltree.h"
#include "log.h"
#include "dbg.h"
#include "sock.h"
int cw_in_check_disc_req(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len,struct sockaddr *from)
{
cw_action_in_t *mlist[120];
int n = cw_check_missing_mand(mlist, conn, a);
conn->capwap_state = CW_STATE_NONE;
if (n && conn->strict_capwap) {
cw_dbg_missing_mand(DBG_MSG_ERR, conn, mlist, n, a);
/* if mandatory elements are missing, in strict
mode send no discovery response */
cw_dbg(DBG_MSG_ERR,
"Ignoring Discovery Request from %s - missing mandatory elements.",
sock_addr2str(from));
return -1;
}
if ( n ) {
/* put a warning here */
cw_dbg_missing_mand(DBG_RFC, conn, mlist, n, a);
}
/* ok, send response */
return 0;
}

View File

@ -0,0 +1,53 @@
#include <errno.h>
#include "capwap.h"
#include "capwap_items.h"
#include "intavltree.h"
#include "log.h"
#include "dbg.h"
#include "sock.h"
int cw_in_check_disc_resp(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len,struct sockaddr *from)
{
cw_action_in_t *mlist[20];
int n = cw_check_missing_mand(mlist, conn, a);
//cw_dbg(DBG_INFO,"This response came from: %s",sock_addr2str(&conn->addr));
/* if mandatory elements are missing, ignore this response */
if (n && conn->strict_capwap) {
cw_dbg_missing_mand(DBG_MSG_ERR, conn, mlist, n, a);
cw_dbg(DBG_MSG_ERR,
"Ignoring Discovery Response from %s - missing mandatory elements.",
sock_addr2str(from));
errno = EAGAIN;
return -1;
}
if (n) {
cw_dbg_missing_mand(DBG_RFC, conn, mlist, n, a);
}
/* we have all AC information in the incomming buffer */
mbag_t discs;
discs = mbag_get_mavl_c(conn->remote, CW_ITEM_DISCOVERIES,
mbag_i_create);
//mavl_del_all(discs);
//exit(0);
if ( !discs ) {
cw_log(LOG_ERR,"Can't allocate store for disc resp");
errno = ENOMEM;
return -1;
}
mbag_i_set_mavl(discs,discs->count,conn->incomming);
conn->incomming = mbag_create();
return 0;
}

View File

@ -0,0 +1,55 @@
#include <stdio.h>
#include <errno.h>
#include "capwap.h"
#include "dbg.h"
#include "log.h"
#include "capwap_items.h"
int cw_in_check_img_data_req_ac(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len,struct sockaddr *from)
{
/* Check for mandatory elements */
cw_action_in_t * mlist[60];
int n = cw_check_missing_mand(mlist,conn,a);
if (n) {
cw_dbg_missing_mand(DBG_ELEM,conn,mlist,n,a);
conn->capwap_state=CW_STATE_JOIN;
return CW_RESULT_MISSING_MAND_ELEM;
}
struct mbag_item *i = mbag_get(conn->incomming,CW_ITEM_IMAGE_IDENTIFIER);
if (i) {
uint32_t vendor_id = vendorstr_get_vendor_id(i->data);
const char * image_dir;
image_dir = mbag_get_str(conn->local,CW_ITEM_AC_IMAGE_DIR,"./img");
char * image_filename = malloc(6+vendorstr_len(i->data)+1+strlen(image_dir));
if (!image_filename)
return CW_RESULT_IMAGE_DATA_ERROR;
sprintf(image_filename,"%s%04X/%s",image_dir,vendor_id,vendorstr_data(i->data));
FILE *infile = fopen(image_filename,"rb");
if (!infile){
cw_log(LOG_WARNING,"Can't open image file: %s - %s - requestet by WTP",
image_filename,strerror(errno));
free(image_filename);
return CW_RESULT_IMAGE_DATA_ERROR;
}
mbag_set_str(conn->outgoing,CW_ITEM_IMAGE_FILENAME,image_filename);
mbag_set_dword(conn->outgoing,CW_ITEM_RESULT_CODE,0);
conn->capwap_state=CW_STATE_IMAGE_DATA;
return 0;
}
return CW_RESULT_IMAGE_DATA_ERROR;
}

View File

@ -0,0 +1,66 @@
#include <stdio.h>
#include <errno.h>
#include "capwap.h"
#include "dbg.h"
#include "log.h"
#include "capwap_items.h"
#include <unistd.h> //Tube
int cw_in_check_img_data_req_wtp(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len,struct sockaddr *from)
{
mbag_set_dword(conn->outgoing,CW_ITEM_RESULT_CODE,0);
conn->capwap_state=CW_STATE_IMAGE_DATA;
//usleep(100000);
return 0;
return CW_RESULT_IMAGE_DATA_ERROR;
return 0;
/* Check for mandatory elements */
cw_action_in_t * mlist[60];
int n = cw_check_missing_mand(mlist,conn,a);
if (n) {
cw_dbg_missing_mand(DBG_ELEM,conn,mlist,n,a);
conn->capwap_state=CW_STATE_JOIN;
return CW_RESULT_MISSING_MAND_ELEM;
}
struct mbag_item *i = mbag_get(conn->incomming,CW_ITEM_IMAGE_IDENTIFIER);
if (i) {
uint32_t vendor_id = vendorstr_get_vendor_id(i->data);
const char * image_dir;
image_dir = mbag_get_str(conn->local,CW_ITEM_AC_IMAGE_DIR,"./img");
char * image_filename = malloc(6+vendorstr_len(i->data)+1+strlen(image_dir));
if (!image_filename)
return CW_RESULT_IMAGE_DATA_ERROR;
sprintf(image_filename,"%s%04X/%s",image_dir,vendor_id,vendorstr_data(i->data));
FILE *infile = fopen(image_filename,"rb");
if (!infile){
cw_log(LOG_WARNING,"Can't open image file: %s - %s - requestet by WTP",
image_filename,strerror(errno));
free(image_filename);
return CW_RESULT_IMAGE_DATA_ERROR;
}
mbag_set_str(conn->outgoing,CW_ITEM_IMAGE_FILENAME,image_filename);
mbag_set_dword(conn->outgoing,CW_ITEM_RESULT_CODE,0);
conn->capwap_state=CW_STATE_IMAGE_DATA;
return 0;
}
return CW_RESULT_IMAGE_DATA_ERROR;
}

View File

@ -0,0 +1,34 @@
#include <stdio.h>
#include <errno.h>
#include "capwap.h"
#include "dbg.h"
#include "log.h"
#include "capwap_items.h"
int cw_in_check_img_data_resp(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len, struct sockaddr *from)
{
cw_action_in_t * mlist[60];
/* Check for mandatory elements */
int n = cw_check_missing_mand(mlist,conn,a);
if (n) {
cw_dbg_missing_mand(DBG_ELEM,conn,mlist,n,a);
conn->capwap_state=CW_STATE_JOIN;
errno=EAGAIN;
return -1; //CW_RESULT_MISSING_MAND_ELEM;
}
mbag_item_t * iresult = mbag_get(conn->incomming, CW_ITEM_RESULT_CODE);
if ( iresult ) {
return iresult->dword;
}
return 0;
}

View File

@ -0,0 +1,31 @@
#include "capwap.h"
#include "intavltree.h"
#include "dbg.h"
#include "log.h"
#include "capwap_items.h"
int cw_in_check_join_req(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len,struct sockaddr *from)
{
cw_action_in_t * mlist[60];
/* Check for mandatory elements */
int n = cw_check_missing_mand(mlist,conn,a);
if (n) {
if ( conn->strict_capwap ){
cw_dbg_missing_mand(DBG_MSG_ERR,conn,mlist,n,a);
conn->capwap_state=CW_STATE_JOIN;
return CW_RESULT_MISSING_MAND_ELEM;
}
cw_dbg_missing_mand(DBG_RFC,conn,mlist,n,a);
}
/* set result code to ok and change to configure state */
mbag_set_dword(conn->outgoing,CW_ITEM_RESULT_CODE,0);
conn->capwap_state = CW_STATE_CONFIGURE;
return 0;
}

View File

@ -0,0 +1,3 @@

View File

@ -0,0 +1,49 @@
#include <errno.h>
#include "capwap.h"
#include "intavltree.h"
#include "dbg.h"
#include "log.h"
#include "capwap_items.h"
int cw_in_check_join_resp(struct conn *conn, struct cw_action_in *a, uint8_t * data,
int len,struct sockaddr *from)
{
cw_action_in_t * mlist[60];
mbag_item_t * jresult = mbag_get(conn->incomming,CW_ITEM_RESULT_CODE);
if (jresult ) {
if (!cw_rcok(jresult->dword)){
return jresult->dword;
}
}
/* Check for mandatory elements */
int n = cw_check_missing_mand(mlist,conn,a);
if (n && conn->strict_capwap) {
cw_dbg_missing_mand(DBG_MSG_ERR,conn,mlist,n,a);
conn->capwap_state=CW_STATE_JOIN;
errno=EAGAIN;
return -1; //CW_RESULT_MISSING_MAND_ELEM;
}
if (n){
cw_dbg_missing_mand(DBG_RFC,conn,mlist,n,a);
}
if ( jresult ) {
return jresult->dword;
}
/* set result code to ok and change to configure state */
// mbag_set_dword(conn->outgoing,CW_ITEM_RESULT_CODE,0);
return 0;
}

View File

@ -0,0 +1,143 @@
#include "action.h"
#include "dbg.h"
#include "log.h"
#include "mbag.h"
#include "capwap.h"
#include "capwap_items.h"
int cw_cisco_get_wlan_legacy(mbag_t wlan, uint8_t *data, int len)
{
mbag_set_word(wlan,"enc_capab", cw_get_word(data+1));
int wlan_id=cw_get_word(data+3);
mbag_set_word(wlan,"wlan_id",wlan_id);
mbag_set_dword(wlan,"enc_policy",cw_get_dword(data+5));
mbag_set_bstr16n(wlan,"key",data+9,32);
mbag_set_byte(wlan,"key_index",cw_get_byte(data+41));
mbag_set_byte(wlan,"key_shared",cw_get_byte(data+42));
mbag_set_byte(wlan,"wpa_len",cw_get_byte(data+43));
mbag_set_bstr16n(wlan,"wpa_data",data+44,32);
mbag_set_byte(wlan,"rsn_len",cw_get_byte(data+76));
mbag_set_bstr16n(wlan,"rsn_data",data+77,64);
mbag_set_bstr16n(wlan,"reserved",data+141,49);
mbag_set_byte(wlan,"wme_len",cw_get_byte(data+190));
mbag_set_bstr16n(wlan,"wme_data",data+191,32);
mbag_set_byte(wlan,"dot11e_len",cw_get_byte(data+223));
mbag_set_bstr16n(wlan,"dot11e_data",data+224,32);
mbag_set_byte(wlan,"qos",cw_get_byte(data+256));
// mbag_set_byte(wlan,"ssid_broadcast",cw_get_byte(data+257));
mbag_set_byte(wlan,"ssid_broadcast",cw_get_byte(data+435));
mbag_set_byte(wlan,"aironet_ie",cw_get_byte(data+436));
mbag_set_bstr16n(wlan,"reserved2",data+258,40);
mbag_set_byte(wlan,"dtim_period",cw_get_byte(data+554));
mbag_set_bstr16n(wlan,"wlan_name",data+558,32);
mbag_set_byte(wlan,"allow_aaa_override",cw_get_byte(data+591));
mbag_set_byte(wlan,"max_clients",cw_get_byte(data+593));
mbag_set_bstr16n(wlan,"ssid",data+622,len-622);
return 0;
}
int cw_cisco_get_wlan_(mbag_t wlan, uint8_t *data, int len)
{
mbag_set_word(wlan,"enc_capab", cw_get_word(data+1));
int wlan_id=cw_get_word(data+3);
mbag_set_word(wlan,"wlan_id",wlan_id);
mbag_set_dword(wlan,"enc_policy",cw_get_dword(data+5));
mbag_set_bstr16n(wlan,"key",data+9,32);
mbag_set_byte(wlan,"key_index",cw_get_byte(data+41));
mbag_set_byte(wlan,"key_shared",cw_get_byte(data+42));
mbag_set_byte(wlan,"wpa_len",cw_get_byte(data+43));
mbag_set_bstr16n(wlan,"wpa_data",data+44,32);
mbag_set_byte(wlan,"rsn_len",cw_get_byte(data+76));
mbag_set_bstr16n(wlan,"rsn_data",data+77,64);
mbag_set_bstr16n(wlan,"reserved",data+141,49);
mbag_set_byte(wlan,"wme_len",cw_get_byte(data+190));
mbag_set_bstr16n(wlan,"wme_data",data+191,32);
mbag_set_byte(wlan,"dot11e_len",cw_get_byte(data+223));
mbag_set_bstr16n(wlan,"dot11e_data",data+224,32);
mbag_set_byte(wlan,"qos",cw_get_byte(data+256));
// mbag_set_byte(wlan,"ssid_broadcast",cw_get_byte(data+257));
mbag_set_byte(wlan,"ssid_broadcast",cw_get_byte(data+435));
mbag_set_byte(wlan,"aironet_ie",cw_get_byte(data+436));
mbag_set_bstr16n(wlan,"reserved2",data+258,40);
mbag_set_byte(wlan,"dtim_period",cw_get_byte(data+554));
mbag_set_bstr16n(wlan,"wlan_name",data+558,32);
mbag_set_byte(wlan,"allow_aaa_override",cw_get_byte(data+591));
mbag_set_byte(wlan,"max_clients",cw_get_byte(data+593));
mbag_set_bstr16n(wlan,"ssid",data+622,len-622);
return 0;
}
int cw_in_cisco_add_wlan(struct conn *conn, struct cw_action_in *a, uint8_t * data, int len,
struct sockaddr *from)
{
int rid = cw_get_byte(data);
mbag_t wlan = mbag_i_get_mbag(conn->radios,rid,NULL);
if ( !wlan ) {
printf("No Radio git\n");
}
mbag_set_byte(wlan,"radio_id",rid);
int mytype=mbag_get_byte(conn->config,CW_ITEM_AP_MODE_AND_TYPE,77) & 0xff;
printf("My type: %d\n",mytype);
exit(0);
cw_cisco_get_wlan_legacy(wlan,data,len);
return 0;
}

Some files were not shown because too many files have changed in this diff Show More