renamed capwap directory to cw.
FossilOrigin-Name: 8a43dd9d05a4cb73210243ddd8df2a26f16c7ef2c4d4e36ab446de1f65d88223
This commit is contained in:
2303
src/cw/Doxyfile
Normal file
2303
src/cw/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
339
src/cw/Makefile
Normal file
339
src/cw/Makefile
Normal 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
78
src/cw/acinfo_print.c
Normal 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
78
src/cw/aciplist.c
Normal 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
24
src/cw/aciplist.h
Normal 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
74
src/cw/acpriolist.c
Normal 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
39
src/cw/acpriolist.h
Normal 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
359
src/cw/action.c
Normal 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
184
src/cw/action.h
Normal 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
69
src/cw/avliter_next.c
Normal 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
66
src/cw/avliter_seek.c
Normal 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
45
src/cw/avltree.h
Normal 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
36
src/cw/avltree_del_all.c
Normal 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
39
src/cw/avltree_foreach.c
Normal 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);
|
||||
}
|
||||
|
31
src/cw/avltree_foreach_from_lr.c
Normal file
31
src/cw/avltree_foreach_from_lr.c
Normal 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);
|
||||
}
|
||||
|
||||
|
17
src/cw/avltree_foreach_lr.c
Normal file
17
src/cw/avltree_foreach_lr.c
Normal 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);
|
||||
|
||||
}
|
||||
|
||||
|
33
src/cw/avltree_foreach_node.c
Normal file
33
src/cw/avltree_foreach_node.c
Normal 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)
|
||||
{
|
||||
|
||||
}
|
18
src/cw/avltree_foreach_rl.c
Normal file
18
src/cw/avltree_foreach_rl.c
Normal 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
47
src/cw/avltree_get.c
Normal 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
39
src/cw/avltree_get_node.c
Normal 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
172
src/cw/bstr.h
Normal 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
|
||||
|
||||
/**@}*/
|
||||
|
30
src/cw/bstr16_create_from_str.c
Normal file
30
src/cw/bstr16_create_from_str.c
Normal 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
67
src/cw/bstr16cfgstr.c
Normal 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
45
src/cw/bstr_create.c
Normal 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;
|
||||
}
|
90
src/cw/bstr_create_from_cfgstr.c
Normal file
90
src/cw/bstr_create_from_cfgstr.c
Normal 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;
|
||||
}
|
||||
|
||||
|
31
src/cw/bstr_create_from_str.c
Normal file
31
src/cw/bstr_create_from_str.c
Normal 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
12
src/cw/bstr_replace.c
Normal 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
38
src/cw/bstr_to_str.c
Normal 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
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
102
src/cw/capwap_80211.h
Normal 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
|
||||
|
||||
|
13
src/cw/capwap_80211_actions.h
Normal file
13
src/cw/capwap_80211_actions.h
Normal 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 */
|
||||
|
||||
|
65
src/cw/capwap_80211_actions_ac.c
Normal file
65
src/cw/capwap_80211_actions_ac.c
Normal 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;
|
||||
}
|
||||
|
64
src/cw/capwap_80211_actions_wtp.c
Normal file
64
src/cw/capwap_80211_actions_wtp.c
Normal 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;
|
||||
}
|
||||
|
60
src/cw/capwap_action_helpers.c
Normal file
60
src/cw/capwap_action_helpers.c
Normal 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
196
src/cw/capwap_actions.h
Normal 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
393
src/cw/capwap_actions_ac.c
Normal 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
395
src/cw/capwap_actions_wtp.c
Normal 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
239
src/cw/capwap_cisco.h
Normal 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
17
src/cw/capwap_crypto.h
Normal 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
148
src/cw/capwap_items.c
Normal 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
180
src/cw/capwap_items.h
Normal 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
25
src/cw/capwap_msg_new.c
Normal 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()
|
||||
{
|
||||
|
||||
|
||||
}
|
67
src/cw/capwap_strings_elem.c
Normal file
67
src/cw/capwap_strings_elem.c
Normal 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"}
|
||||
|
||||
};
|
12
src/cw/capwap_strings_elem80211.c
Normal file
12
src/cw/capwap_strings_elem80211.c
Normal 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 "}
|
||||
|
||||
};
|
9
src/cw/capwap_strings_item.c
Normal file
9
src/cw/capwap_strings_item.c
Normal 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"}
|
||||
|
||||
}
|
63
src/cw/capwap_strings_msg.c
Normal file
63
src/cw/capwap_strings_msg.c
Normal 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"}
|
||||
|
||||
};
|
||||
|
||||
|
17
src/cw/capwap_strings_result.c
Normal file
17
src/cw/capwap_strings_result.c
Normal 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"}
|
||||
|
||||
};
|
||||
|
11
src/cw/capwap_strings_state.c
Normal file
11
src/cw/capwap_strings_state.c
Normal 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" },
|
||||
};
|
||||
|
11
src/cw/capwap_strings_vendor.c
Normal file
11
src/cw/capwap_strings_vendor.c
Normal 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
14
src/cw/cipwap.h
Normal 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
43
src/cw/cipwap_actions.h
Normal 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
190
src/cw/cipwap_actions_ac.c
Normal 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
169
src/cw/cipwap_actions_wtp.c
Normal 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;
|
||||
}
|
17
src/cw/cipwap_strings_elem.c
Normal file
17
src/cw/cipwap_strings_elem.c
Normal 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
171
src/cw/cisco.c
Normal 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
278
src/cw/conn.h
Normal 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
102
src/cw/conn_create.c
Normal 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
82
src/cw/conn_create_noq.c
Normal 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
33
src/cw/conn_destroy.c
Normal 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);
|
||||
}
|
||||
|
||||
|
35
src/cw/conn_detect_capwap.c
Normal file
35
src/cw/conn_detect_capwap.c
Normal 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
78
src/cw/conn_get_message.c
Normal 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;
|
||||
}
|
44
src/cw/conn_get_response.c
Normal file
44
src/cw/conn_get_response.c
Normal 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
51
src/cw/conn_init.c
Normal 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;
|
||||
}
|
||||
|
||||
|
12
src/cw/conn_prepare_configuration_update_request.c
Normal file
12
src/cw/conn_prepare_configuration_update_request.c
Normal 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);
|
||||
}
|
59
src/cw/conn_prepare_image_data_request.c
Normal file
59
src/cw/conn_prepare_image_data_request.c
Normal 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;
|
||||
}
|
10
src/cw/conn_prepare_request.c
Normal file
10
src/cw/conn_prepare_request.c
Normal 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;
|
||||
}
|
546
src/cw/conn_process_packet.c
Normal file
546
src/cw/conn_process_packet.c
Normal 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;
|
||||
}
|
529
src/cw/conn_process_packet2.c
Normal file
529
src/cw/conn_process_packet2.c
Normal 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;
|
||||
}
|
52
src/cw/conn_q_add_packet.c
Normal file
52
src/cw/conn_q_add_packet.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
38
src/cw/conn_q_get_packet.c
Normal file
38
src/cw/conn_q_get_packet.c
Normal 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,×pec);
|
||||
timespec.tv_sec++;
|
||||
|
||||
/* wait one second to get a packet */
|
||||
if (sem_timedwait(&conn->q_sem,×pec)==-1){
|
||||
return NULL;
|
||||
};
|
||||
|
||||
int qrpos = conn->qrpos+1;
|
||||
if (qrpos==conn->qsize)
|
||||
qrpos=0;
|
||||
conn->qrpos=qrpos;
|
||||
return conn->q[qrpos];
|
||||
}
|
71
src/cw/conn_q_recv_packet.c
Normal file
71
src/cw/conn_q_recv_packet.c
Normal 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
76
src/cw/conn_recv_packet.c
Normal 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
107
src/cw/conn_send_msg.c
Normal 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
50
src/cw/conn_send_packet.c
Normal 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;
|
||||
}
|
61
src/cw/conn_send_request.c
Normal file
61
src/cw/conn_send_request.c
Normal 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;
|
||||
}
|
||||
|
37
src/cw/conn_wait_for_message.c
Normal file
37
src/cw/conn_wait_for_message.c
Normal 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;
|
||||
}
|
||||
|
||||
|
78
src/cw/conn_wait_for_request.c
Normal file
78
src/cw/conn_wait_for_request.c
Normal 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
101
src/cw/connlist.c
Normal 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
19
src/cw/cw.h
Normal 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
|
79
src/cw/cw_addelem_capwap_local_ip_addr.c
Normal file
79
src/cw/cw_addelem_capwap_local_ip_addr.c
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
26
src/cw/cw_addelem_cisco_wtp_radio_cfg.c
Normal file
26
src/cw/cw_addelem_cisco_wtp_radio_cfg.c
Normal 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);
|
||||
}
|
||||
|
48
src/cw/cw_addelem_vendor_specific_payload.c
Normal file
48
src/cw/cw_addelem_vendor_specific_payload.c
Normal 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;
|
||||
|
||||
}
|
36
src/cw/cw_check_missing_mand.c
Normal file
36
src/cw/cw_check_missing_mand.c
Normal 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
145
src/cw/cw_cisco_id_to_str.c
Normal 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
23
src/cw/cw_get_mod_ac.c
Normal 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;
|
||||
}
|
130
src/cw/cw_in_ac_descriptor.c
Normal file
130
src/cw/cw_in_ac_descriptor.c
Normal 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;
|
||||
}
|
||||
|
30
src/cw/cw_in_ac_name_with_priority.c
Normal file
30
src/cw/cw_in_ac_name_with_priority.c
Normal 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;
|
||||
}
|
||||
|
50
src/cw/cw_in_capwap_control_ipv4_address.c
Normal file
50
src/cw/cw_in_capwap_control_ipv4_address.c
Normal 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;
|
||||
}
|
31
src/cw/cw_in_check_cfg_update_req.c
Normal file
31
src/cw/cw_in_check_cfg_update_req.c
Normal 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;
|
||||
}
|
13
src/cw/cw_in_check_chng_state_evnt_req.c
Normal file
13
src/cw/cw_in_check_chng_state_evnt_req.c
Normal 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;
|
||||
}
|
62
src/cw/cw_in_check_cipwap_join_req.c
Normal file
62
src/cw/cw_in_check_cipwap_join_req.c
Normal 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;
|
||||
}
|
40
src/cw/cw_in_check_disc_req.c
Normal file
40
src/cw/cw_in_check_disc_req.c
Normal 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;
|
||||
}
|
53
src/cw/cw_in_check_disc_resp.c
Normal file
53
src/cw/cw_in_check_disc_resp.c
Normal 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;
|
||||
}
|
55
src/cw/cw_in_check_img_data_req_ac.c
Normal file
55
src/cw/cw_in_check_img_data_req_ac.c
Normal 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;
|
||||
|
||||
}
|
66
src/cw/cw_in_check_img_data_req_wtp.c
Normal file
66
src/cw/cw_in_check_img_data_req_wtp.c
Normal 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;
|
||||
|
||||
}
|
34
src/cw/cw_in_check_img_data_resp.c
Normal file
34
src/cw/cw_in_check_img_data_resp.c
Normal 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;
|
||||
|
||||
}
|
31
src/cw/cw_in_check_join_req.c
Normal file
31
src/cw/cw_in_check_join_req.c
Normal 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;
|
||||
}
|
3
src/cw/cw_in_check_join_request.c
Normal file
3
src/cw/cw_in_check_join_request.c
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
|
49
src/cw/cw_in_check_join_resp.c
Normal file
49
src/cw/cw_in_check_join_resp.c
Normal 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;
|
||||
}
|
143
src/cw/cw_in_cisco_add_wlan.c
Normal file
143
src/cw/cw_in_cisco_add_wlan.c
Normal 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
Reference in New Issue
Block a user