From 2bae9358d7e8fb05824bf714b63114e1af21c3f7 Mon Sep 17 00:00:00 2001 From: "7u83@mail.ru" <7u83@mail.ru@noemail.net> Date: Fri, 11 Jul 2014 20:12:11 +0000 Subject: [PATCH] Initial commit FossilOrigin-Name: c53d95729c009f8f80a7d63847cef7668ff73f8af0523ab65f7734696f85399c --- src/ac/Makefile | 63 ++ src/ac/ac.default.conf | 27 + src/ac/ac_interface.c | 102 +++ src/ac/ac_main.c | 219 ++++++ src/ac/actube.h | 2 + src/ac/conf.c | 493 +++++++++++++ src/ac/conf.h | 94 +++ src/ac/db.c | 35 + src/ac/socklist.c | 341 +++++++++ src/ac/socklist.h | 51 ++ src/ac/wtplist.c | 149 ++++ src/ac/wtplist.h | 18 + src/ac/wtpman.c | 286 ++++++++ src/ac/wtpman.h | 62 ++ src/capwap/Makefile | 161 +++++ src/capwap/acinfo.c | 166 +++++ src/capwap/acinfo.h | 62 ++ src/capwap/acinfo_print.c | 59 ++ src/capwap/aciplist.c | 53 ++ src/capwap/avltree.c | 669 ++++++++++++++++++ src/capwap/avltree.h | 64 ++ src/capwap/avltree.old.c | 564 +++++++++++++++ src/capwap/avltree_del_all.c | 36 + src/capwap/avltree_foreach.c | 51 ++ src/capwap/avltree_get.c | 37 + src/capwap/capwap.h | 338 +++++++++ src/capwap/capwap_ieee80211.h | 29 + src/capwap/capwap_msg_new.c | 25 + src/capwap/capwap_parse_ctrlhdr.c | 41 ++ src/capwap/conn.c | 117 +++ src/capwap/conn.h | 147 ++++ src/capwap/conn_get_message.c | 51 ++ src/capwap/conn_process_packet.c | 152 ++++ src/capwap/conn_q_add_packet.c | 50 ++ src/capwap/conn_q_get_packet.c | 32 + src/capwap/conn_q_recv_packet.c | 50 ++ src/capwap/conn_recv_packet.c | 34 + src/capwap/conn_send_cwmsg.c | 96 +++ src/capwap/conn_send_packet.c | 51 ++ src/capwap/connlist.c | 98 +++ src/capwap/cw_foreach_msgelem.c | 46 ++ src/capwap/cw_log.c | 26 + src/capwap/cw_log.h | 76 ++ src/capwap/cw_log_debug.c | 116 +++ src/capwap/cw_log_tofile.c | 36 + src/capwap/cw_log_tosyslog.c | 20 + src/capwap/cw_msgelemtostr.c | 12 + src/capwap/cw_pseudo_rand.c | 36 + src/capwap/cw_rand.c | 61 ++ src/capwap/cw_setstr.c | 34 + src/capwap/cw_util.h | 31 + src/capwap/cwmsg.h | 34 + src/capwap/cwmsg_addelem.c | 32 + src/capwap/cwmsg_addelem_ac_descriptor.c | 57 ++ src/capwap/cwmsg_addelem_ctrl_ip_addrs.c | 103 +++ src/capwap/cwmsg_addelem_cw_local_ip_addr.c | 55 ++ .../cwmsg_addelem_mtu_discovery_padding.c | 19 + src/capwap/cwmsg_addelem_result_code.c | 10 + src/capwap/cwmsg_addelem_wtp_board_data.c | 37 + src/capwap/cwmsg_addelem_wtp_descriptor.c | 57 ++ src/capwap/cwmsg_addelem_wtp_radio_infos.c | 39 + src/capwap/cwmsg_init.c | 62 ++ src/capwap/cwmsg_init_echo_request.c | 28 + src/capwap/cwmsg_send.c | 91 +++ src/capwap/cwmsg_set_control_header.c | 13 + src/capwap/cwread_discovery_response.c | 61 ++ src/capwap/cwread_join_response.c | 58 ++ src/capwap/cwrmsg.h | 18 + src/capwap/cwsend_discovery_request.c | 39 + src/capwap/cwsend_discovery_response.c | 47 ++ src/capwap/cwsend_echo_request.c | 33 + src/capwap/cwsend_echo_response.c | 17 + src/capwap/cwsend_join_request.c | 52 ++ src/capwap/cwsend_join_response.c | 26 + src/capwap/dtls.h | 30 + src/capwap/dtls_openssl.c | 379 ++++++++++ src/capwap/dtls_openssl.h | 48 ++ src/capwap/dtls_openssl_accept.c | 160 +++++ src/capwap/dtls_openssl_bio.c | 171 +++++ src/capwap/dtls_openssl_connect.c | 98 +++ src/capwap/dtls_openssl_init.c | 41 ++ src/capwap/fragman.c | 203 ++++++ src/capwap/fragman.h | 64 ++ src/capwap/process_discovery_request.c | 48 ++ src/capwap/process_join_request.c | 55 ++ src/capwap/process_msgelems.c | 53 ++ .../process_msgelems_discovery_request.c | 60 ++ src/capwap/radioinfo.h | 32 + src/capwap/sock.h | 70 ++ src/capwap/sock_addrinit.c | 22 + src/capwap/sock_addrlen.c | 61 ++ src/capwap/sock_addrtostr.c | 95 +++ src/capwap/sock_cmpaddr.c | 78 ++ src/capwap/sock_copyaddr.c | 28 + src/capwap/sock_create.c | 65 ++ src/capwap/sock_getbroadcastaddr.c | 31 + src/capwap/sock_getifaddr.c | 72 ++ src/capwap/sock_getifhwaddr.c | 39 + src/capwap/sock_getport.c | 35 + src/capwap/sock_hwaddrtostr.c | 33 + src/capwap/sock_mreceive.c | 61 ++ src/capwap/sock_mwait.c | 46 ++ src/capwap/sock_receive.c | 56 ++ src/capwap/sock_set_dontfrag.c | 25 + src/capwap/sock_set_recvtimeout.c | 14 + src/capwap/sock_setport.c | 21 + src/capwap/sock_strtoaddr.c | 110 +++ src/capwap/stravltree.c | 30 + src/capwap/stravltree.h | 12 + src/capwap/wtpinfo.c | 121 ++++ src/capwap/wtpinfo.h | 80 +++ src/capwap/wtpinfo_print.c | 131 ++++ src/capwap/wtpinfo_readelem_discovery_type.c | 23 + src/capwap/wtpinfo_readelem_location_data.c | 19 + src/capwap/wtpinfo_readelem_session_id.c | 22 + src/capwap/wtpinfo_readelem_wtp_board_data.c | 63 ++ src/capwap/wtpinfo_readelem_wtp_descriptor.c | 62 ++ .../wtpinfo_readelem_wtp_frame_tunnel_mode.c | 22 + src/capwap/wtpinfo_readelem_wtp_mac_type.c | 21 + src/capwap/wtpinfo_readelem_wtp_name.c | 23 + src/capwap/wtpinfo_readelem_wtp_radio_info.c | 22 + src/capwap/wtpinfo_set_location.c | 28 + src/wtp/Makefile | 77 ++ src/wtp/discovery.c | 315 +++++++++ src/wtp/join.c | 127 ++++ src/wtp/run.c | 98 +++ src/wtp/sulking.c | 15 + src/wtp/wtp.defaul.conf | 81 +++ src/wtp/wtp.h | 7 + src/wtp/wtp_conf.c | 254 +++++++ src/wtp/wtp_conf.h | 62 ++ src/wtp/wtp_interface.c | 80 +++ src/wtp/wtp_interface.h | 9 + src/wtp/wtp_main.c | 130 ++++ src/wtp/wtpdrv.c | 72 ++ src/wtp/wtpdrv.h | 4 + 136 files changed, 11071 insertions(+) create mode 100644 src/ac/Makefile create mode 100644 src/ac/ac.default.conf create mode 100644 src/ac/ac_interface.c create mode 100644 src/ac/ac_main.c create mode 100644 src/ac/actube.h create mode 100644 src/ac/conf.c create mode 100644 src/ac/conf.h create mode 100644 src/ac/db.c create mode 100644 src/ac/socklist.c create mode 100644 src/ac/socklist.h create mode 100644 src/ac/wtplist.c create mode 100644 src/ac/wtplist.h create mode 100644 src/ac/wtpman.c create mode 100644 src/ac/wtpman.h create mode 100644 src/capwap/Makefile create mode 100644 src/capwap/acinfo.c create mode 100644 src/capwap/acinfo.h create mode 100644 src/capwap/acinfo_print.c create mode 100644 src/capwap/aciplist.c create mode 100644 src/capwap/avltree.c create mode 100644 src/capwap/avltree.h create mode 100644 src/capwap/avltree.old.c create mode 100644 src/capwap/avltree_del_all.c create mode 100644 src/capwap/avltree_foreach.c create mode 100644 src/capwap/avltree_get.c create mode 100644 src/capwap/capwap.h create mode 100644 src/capwap/capwap_ieee80211.h create mode 100644 src/capwap/capwap_msg_new.c create mode 100644 src/capwap/capwap_parse_ctrlhdr.c create mode 100644 src/capwap/conn.c create mode 100644 src/capwap/conn.h create mode 100644 src/capwap/conn_get_message.c create mode 100644 src/capwap/conn_process_packet.c create mode 100644 src/capwap/conn_q_add_packet.c create mode 100644 src/capwap/conn_q_get_packet.c create mode 100644 src/capwap/conn_q_recv_packet.c create mode 100644 src/capwap/conn_recv_packet.c create mode 100644 src/capwap/conn_send_cwmsg.c create mode 100644 src/capwap/conn_send_packet.c create mode 100644 src/capwap/connlist.c create mode 100644 src/capwap/cw_foreach_msgelem.c create mode 100644 src/capwap/cw_log.c create mode 100644 src/capwap/cw_log.h create mode 100644 src/capwap/cw_log_debug.c create mode 100644 src/capwap/cw_log_tofile.c create mode 100644 src/capwap/cw_log_tosyslog.c create mode 100644 src/capwap/cw_msgelemtostr.c create mode 100644 src/capwap/cw_pseudo_rand.c create mode 100644 src/capwap/cw_rand.c create mode 100644 src/capwap/cw_setstr.c create mode 100644 src/capwap/cw_util.h create mode 100644 src/capwap/cwmsg.h create mode 100644 src/capwap/cwmsg_addelem.c create mode 100644 src/capwap/cwmsg_addelem_ac_descriptor.c create mode 100644 src/capwap/cwmsg_addelem_ctrl_ip_addrs.c create mode 100644 src/capwap/cwmsg_addelem_cw_local_ip_addr.c create mode 100644 src/capwap/cwmsg_addelem_mtu_discovery_padding.c create mode 100644 src/capwap/cwmsg_addelem_result_code.c create mode 100644 src/capwap/cwmsg_addelem_wtp_board_data.c create mode 100644 src/capwap/cwmsg_addelem_wtp_descriptor.c create mode 100644 src/capwap/cwmsg_addelem_wtp_radio_infos.c create mode 100644 src/capwap/cwmsg_init.c create mode 100644 src/capwap/cwmsg_init_echo_request.c create mode 100644 src/capwap/cwmsg_send.c create mode 100644 src/capwap/cwmsg_set_control_header.c create mode 100644 src/capwap/cwread_discovery_response.c create mode 100644 src/capwap/cwread_join_response.c create mode 100644 src/capwap/cwrmsg.h create mode 100644 src/capwap/cwsend_discovery_request.c create mode 100644 src/capwap/cwsend_discovery_response.c create mode 100644 src/capwap/cwsend_echo_request.c create mode 100644 src/capwap/cwsend_echo_response.c create mode 100644 src/capwap/cwsend_join_request.c create mode 100644 src/capwap/cwsend_join_response.c create mode 100644 src/capwap/dtls.h create mode 100644 src/capwap/dtls_openssl.c create mode 100644 src/capwap/dtls_openssl.h create mode 100644 src/capwap/dtls_openssl_accept.c create mode 100644 src/capwap/dtls_openssl_bio.c create mode 100644 src/capwap/dtls_openssl_connect.c create mode 100644 src/capwap/dtls_openssl_init.c create mode 100644 src/capwap/fragman.c create mode 100644 src/capwap/fragman.h create mode 100644 src/capwap/process_discovery_request.c create mode 100644 src/capwap/process_join_request.c create mode 100644 src/capwap/process_msgelems.c create mode 100644 src/capwap/process_msgelems_discovery_request.c create mode 100644 src/capwap/radioinfo.h create mode 100644 src/capwap/sock.h create mode 100644 src/capwap/sock_addrinit.c create mode 100644 src/capwap/sock_addrlen.c create mode 100644 src/capwap/sock_addrtostr.c create mode 100644 src/capwap/sock_cmpaddr.c create mode 100644 src/capwap/sock_copyaddr.c create mode 100644 src/capwap/sock_create.c create mode 100644 src/capwap/sock_getbroadcastaddr.c create mode 100644 src/capwap/sock_getifaddr.c create mode 100644 src/capwap/sock_getifhwaddr.c create mode 100644 src/capwap/sock_getport.c create mode 100644 src/capwap/sock_hwaddrtostr.c create mode 100644 src/capwap/sock_mreceive.c create mode 100644 src/capwap/sock_mwait.c create mode 100644 src/capwap/sock_receive.c create mode 100644 src/capwap/sock_set_dontfrag.c create mode 100644 src/capwap/sock_set_recvtimeout.c create mode 100644 src/capwap/sock_setport.c create mode 100644 src/capwap/sock_strtoaddr.c create mode 100644 src/capwap/stravltree.c create mode 100644 src/capwap/stravltree.h create mode 100644 src/capwap/wtpinfo.c create mode 100644 src/capwap/wtpinfo.h create mode 100644 src/capwap/wtpinfo_print.c create mode 100644 src/capwap/wtpinfo_readelem_discovery_type.c create mode 100644 src/capwap/wtpinfo_readelem_location_data.c create mode 100644 src/capwap/wtpinfo_readelem_session_id.c create mode 100644 src/capwap/wtpinfo_readelem_wtp_board_data.c create mode 100644 src/capwap/wtpinfo_readelem_wtp_descriptor.c create mode 100644 src/capwap/wtpinfo_readelem_wtp_frame_tunnel_mode.c create mode 100644 src/capwap/wtpinfo_readelem_wtp_mac_type.c create mode 100644 src/capwap/wtpinfo_readelem_wtp_name.c create mode 100644 src/capwap/wtpinfo_readelem_wtp_radio_info.c create mode 100644 src/capwap/wtpinfo_set_location.c create mode 100644 src/wtp/Makefile create mode 100644 src/wtp/discovery.c create mode 100644 src/wtp/join.c create mode 100644 src/wtp/run.c create mode 100644 src/wtp/sulking.c create mode 100644 src/wtp/wtp.defaul.conf create mode 100644 src/wtp/wtp.h create mode 100644 src/wtp/wtp_conf.c create mode 100644 src/wtp/wtp_conf.h create mode 100644 src/wtp/wtp_interface.c create mode 100644 src/wtp/wtp_interface.h create mode 100644 src/wtp/wtp_main.c create mode 100644 src/wtp/wtpdrv.c create mode 100644 src/wtp/wtpdrv.h diff --git a/src/ac/Makefile b/src/ac/Makefile new file mode 100644 index 00000000..bf719689 --- /dev/null +++ b/src/ac/Makefile @@ -0,0 +1,63 @@ +ifndef CC + CC=gcc +endif +SYSARCH := $(shell uname -m) +ifndef ARCH + ARCH=$(SYSARCH) +endif + +LDFLAGS = -g -D_REENTRANT -L/usr/local/lib -L../capwap/$(ARCH) + +CFLAGS = -Wall -g -O0 -D_REENTRANT -DCW_NO_DTLS -DIPV6 -I/usr/local/include -I../capwap + + +LIBS+=-lcapwap +LIBS+=-lrt +LIBS+=-lssl +LIBS+=-lcrypto +LIBS+=-lpthread +LIBS+=-lconfuse +LIBS+=-lsqlite3 + + + +CFLAGS += -DWITH_CW_LOG +CFLAGS += -DWITH_CW_LOG_DEBUG +CFLAGS += -DWITH_RMAC_SUPPORT +CFLAGS += -DWITH_DTLS +CFLAGS += -DWITH_IPV6 + +RM = /bin/rm -f + +# list of generated object files for AC. +AC_OBJS = wtplist.o wtpman.o conf.o ac_main.o \ + ac_interface.o \ + socklist.o \ + db.o \ + +AC_SRCS = $(AC_OBJS:.o=.c) +AC_DEPS := $(AC_OBJS:.o=.d) + +AC_NAME = actube + +.PHONY: deps clean clean_libs libs + +# top-level rule, to compile everything. +all: $(AC_NAME) + +#$(WTP_NAME) $(WUA_NAME) + +$(AC_NAME): $(AC_OBJS) + $(CC) $(AC_OBJS) $(CC_FLAGS) $(OPENSSL_INCLUDE) -o $(AC_NAME) $(LDFLAGS) $(LIBS) + + +clean: + $(RM) $(AC_NAME) $(AC_OBJS) $(AC_DEPS) + +clean_deps: + $(AC_DEPS) + +deps: $(AC_SRC) + $(CC) -MD -E $(AC_SRCS) $(CFLAGS) >/dev/null + +-include $(AC_DEPS) diff --git a/src/ac/ac.default.conf b/src/ac/ac.default.conf new file mode 100644 index 00000000..b432c97e --- /dev/null +++ b/src/ac/ac.default.conf @@ -0,0 +1,27 @@ +# +# Use IPv4 protocol +# +# ipv4=true + +# +# Use IPv6 protocol +# +# ipv6=true +# + +# Listen addresses +# +# listen = +# listen = 192.168.0.15 + + +# +# dtls_psk = +# +# dtls_psk = + + +# ac_name +# The name reported by actube +# +# ac_name = AC diff --git a/src/ac/ac_interface.c b/src/ac/ac_interface.c new file mode 100644 index 00000000..d337e814 --- /dev/null +++ b/src/ac/ac_interface.c @@ -0,0 +1,102 @@ +#include +#include + +#include +#include + +#include "sock.h" + +#include "socklist.h" +#include "acinfo.h" +#include "conf.h" + +#include "capwap.h" + +ACIPLIST * get_aciplist() +{ + int i=0; + + ACIPLIST * aciplist = aciplist_create(); + if(!aciplist) + return 0; + + + for (i=0; iip,(struct sockaddr*)&sa); + acip->wtp_count=17; + + + aciplist_add(aciplist,acip); + + + } + return aciplist; +} + + + + + + +struct ac_info * get_acinfo() +{ + + struct ac_info * acinfo; + acinfo = malloc(sizeof(struct ac_info)); + if(!acinfo) + return 0; + + memset(acinfo,0,sizeof(struct ac_info)); + acinfo->ac_name=conf_acname; + + acinfo->stations=10; + acinfo->limit=10000; + acinfo->active_wtps=10; + acinfo->max_wtps=conf_max_wtps; + acinfo->rmac=2; /* radio mac not supported */ + + acinfo->vendor_id=conf_vendor_id; + acinfo->hardware_version=(uint8_t*)conf_hardware_version; + acinfo->software_version=(uint8_t*)conf_software_version; + + if (conf_dtls_psk) + acinfo->security|=AC_SECURITY_S; + + acinfo->dtls_policy = AC_DTLS_POLICY_C; +// acinfo->ac_ips = conf_ac_ips; +// acinfo->ac_ips_len=conf_ac_ips_len; + +// acinfo->salist=conf_salist; +// acinfo->salist_len=conf_salist_len; + +// acinfo->salist = conf_ac_ips; +// acinfo->salist_len = conf_ac_ips_len; + + acinfo->aciplist=get_aciplist(); + + + return acinfo; + +} + + + +get_join_result() +{ + return 0; +} + diff --git a/src/ac/ac_main.c b/src/ac/ac_main.c new file mode 100644 index 00000000..65a4558a --- /dev/null +++ b/src/ac/ac_main.c @@ -0,0 +1,219 @@ +/* + This file is part of actube. + + actube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include "actube.h" +#include "wtplist.h" +#include "dtls.h" +#include "cw_log.h" +#include "conf.h" +#include "sock.h" + +#include "socklist.h" + +int ac_run(); + +int main (int argc, const char * argv[]) +{ + + cw_log_name="AC-Tube"; + + read_config("ac.conf"); + cw_log_debug_level=conf_debug_level; + + test_db(); + + + + cw_log(LOG_INFO,"Starting AC-Tube"); + +#ifdef WITH_DTLS + dtls_init(); +#endif + if (!socklist_init()) + goto errX; + + if (!wtplist_init()) + goto errX; + + + int rc = ac_run(); +errX: + wtplist_destroy(); + socklist_destroy(); + return rc; +} + +void process_ctrl_packet(int index, struct sockaddr * addr, uint8_t * buffer, int len); + +int ac_run() +{ + + if (!conf_listen_addrs_len){ + cw_log(LOG_ERR,"Fatal error: No listen addresses found."); + return 1; + } + + + + /* it is important to create the unicast sockets first, + * because when we create the mcast an bcast sockets next + * we will look for already created sockets to find a + * good unicast reply socket */ + + int i; + for(i=0; imax) + max=socklist[i].sockfd; + } + + /* wait for an event */ + int n; + while((n=select(max+1, &fset, NULL, NULL, NULL)) < 0) { + if (errno != EINTR) + return n; + + } + + /* process the received packet */ + for( i=0; i. +*/ + +#include +#include +#include + +#include + +#include "capwap.h" +#include "sock.h" + +#include "conf.h" + +#include "cw_log.h" +#include "cw_util.h" + +char * conf_acname = NULL; +int conf_acname_len = 0; + +long conf_max_wtps = CONF_DEFAULT_MAXWTPS; +char * conf_logfilename=CONF_DEFAULT_LOGFILENAME; +struct sockaddr_storage * conf_salist=NULL; + +char ** conf_listen_addrs; +int conf_listen_addrs_len=0; + + +char ** conf_mcast_groups=0; +int conf_mcast_groups_len=0; + +char ** conf_bcast_addrs=0; +int conf_bcast_addrs_len; + + +struct sockaddr_storage * conf_bsalist=NULL; + +int conf_salist_len=0; +int conf_bsalist_len=0; + +struct sockaddr * conf_ac_ips; +int conf_ac_ips_len; + +char * conf_sslcertfilename=NULL; +char * conf_sslkeyfilename=NULL; +char * conf_dtls_psk=NULL; + +char * conf_ac_hardware_version=NULL; +char * conf_ac_software_version=NULL; +int conf_security=0; +long conf_vendor_id=CONF_DEFAULT_VENDOR_ID; + +char * conf_hardware_version; +char * conf_software_version; + +int conf_use_loopback = 0; + +long conf_debug_level=-1; + +char * conf_db_file =0; + +int conf_ipv4=1; +#ifdef WITH_IPV6 +int conf_ipv6=1; +#endif + + +char * conf_control_port=0; +cfg_bool_t conf_ignore_wtp_source_port = cfg_false; + +static int init_acname() +{ + if (conf_acname == NULL){ + conf_acname=CONF_DEFAULT_ACNAME; + } + conf_acname_len=strlen(conf_acname); + return 1; +} + +static int init_dtls() +{ + if (conf_dtls_psk!=NULL){ + conf_security=CWACSECURITY_FLAGS_S; + } + + return 1; +} + + +static int init_vendor_id() +{ + return 1; +} + +static int init_version() +{ + if (!conf_hardware_version) + { + struct utsname u; + int rc = uname(&u); + if (rc<0) + conf_hardware_version=CONF_DEFAULT_HARDWARE_VERSION; + else{ + char str[265]; + sprintf(str,"%s / %s %s",u.machine,u.sysname,u.release); + conf_hardware_version=strdup(str); + } + } + if (!conf_software_version) + conf_software_version=CONF_DEFAULT_SOFTWARE_VERSION; + return 1; +} + +static int init_control_port() +{ + if (conf_control_port != 0) + return 1; + + char str[30]; + sprintf(str,"%d",CONF_DEFAULT_CONTROL_PORT); + conf_control_port=(char*)cw_setstr((uint8_t**)&conf_control_port,(uint8_t*)str,strlen(str)); + return 1; +} + +#include + +static int init_listen_addrs() +{ + if (conf_listen_addrs!=0) + return 1; + + struct ifaddrs * ifap,*ifa; + + int rc = getifaddrs(&ifap); + if (rc==-1) + return 0; + + /* count the addresses */ + int ctr=0; + for (ifa=ifap; ifa!=0; ifa=ifa->ifa_next){ + if (ifa->ifa_addr->sa_family==AF_INET && conf_ipv4) + ctr++; +#ifdef WITH_IPV6 + if (ifa->ifa_addr->sa_family==AF_INET6 && conf_ipv6) + ctr++; +#endif + } + + conf_listen_addrs = malloc(sizeof(char*)*ctr); + if (!conf_listen_addrs){ + rc=0; + goto errX; + } + memset(conf_listen_addrs,0,sizeof(char*)*ctr); + + + ctr=0; + /* get the addresses */ + for (ifa=ifap; ifa!=0; ifa=ifa->ifa_next){ + char str[100]; + + if(!conf_use_loopback){ + if ((ifa->ifa_flags & IFF_LOOPBACK)){ + continue; + } + + } + + + + if (ifa->ifa_addr->sa_family==AF_INET && conf_ipv4){ + sock_addrtostr(ifa->ifa_addr,str,100); + *strchr(str,':')=0; + conf_listen_addrs[ctr]=(char*)cw_setstr((uint8_t**)&conf_listen_addrs[ctr],(uint8_t*)str,strlen(str)); + if (conf_listen_addrs[ctr]) + ctr++; + + } +#ifdef WITH_IPV6 + if (ifa->ifa_addr->sa_family==AF_INET6 && conf_ipv6){ + sock_addrtostr(ifa->ifa_addr,str,100); + if (strncmp(str,"fe80:",5)==0){ + strcat(str,"%"); + strcat(str,ifa->ifa_name); + } + conf_listen_addrs[ctr]=(char*)cw_setstr((uint8_t**)&conf_listen_addrs[ctr],(uint8_t*)str,strlen(str)); + if (conf_listen_addrs[ctr]) + ctr++; + } +#endif + } + conf_listen_addrs_len=ctr; + rc=1; +errX: + freeifaddrs(ifap); + return rc; +} + + +static char * conf_default_mcast_groups_ipv4[] = { + "224.0.1.140", +}; + + + +#ifdef WITH_IPV6 +static char * conf_default_mcast_groups_ipv6[] = { +/* "ff01:0:0:0:0:0:0:18c", + "ff02:0:0:0:0:0:0:18c%em0", + "ff03:0:0:0:0:0:0:18c", + "ff04:0:0:0:0:0:0:18c", + "ff05:0:0:0:0:0:0:18c", + "ff06:0:0:0:0:0:0:18c" +*/ +}; +#endif + +//#include "avltree" +#include "stravltree.h" + + + +static int add_bcast_addr(void *priv, void * addr) +{ + char *s = (char*)addr; + conf_bcast_addrs[conf_bcast_addrs_len]=strdup(s); + if (conf_bcast_addrs[conf_bcast_addrs_len]!=0) + conf_bcast_addrs_len++; + return 1; +} + +/* + * Initialize broadcast addresses (ipv4 only) + */ +int init_bcast_addrs() +{ + if (conf_bcast_addrs) + return 1; + + if (!conf_ipv4) + return 1; + + struct avltree *t = stravltree_create(); + if (!t) + return 0; + + /* add the default broadast address */ + stravltree_add(t,"255.255.255.255"); + + + /* add all other local broadcast addresses */ + struct ifaddrs * ifa0,*ifa; + int rc = getifaddrs(&ifa0); + if (rc==-1) + return 0; + + for (ifa=ifa0; ifa!=0; ifa=ifa->ifa_next){ + struct sockaddr * sa; + if (!(ifa->ifa_flags & IFF_BROADCAST)) + continue; + + + if(!conf_use_loopback){ + if ((ifa->ifa_flags & IFF_LOOPBACK)) + continue; + } + + + sa = ifa->ifa_addr; + if(sa->sa_family != AF_INET) + continue; + + char str[100]; + if (ifa->ifa_broadaddr){ + sock_addrtostr(ifa->ifa_broadaddr,str,100); + *strchr(str,':')=0; + stravltree_add(t,str); + } + + } + + conf_bcast_addrs=malloc(t->count*sizeof(char*)); + + stravltree_foreach(t,add_bcast_addr,0,1); + stravltree_destroy(t); + + freeifaddrs(ifa0); + + return 1; +} + +int init_mcast_groups() +{ + if (conf_mcast_groups) + return 1; + + int n = 0; + int n4=0,n6=0; + if (conf_ipv4){ + n4=sizeof(conf_default_mcast_groups_ipv4)/sizeof(char*); + } + +#ifdef WITH_IPV6 + if (conf_ipv6){ + n6=sizeof(conf_default_mcast_groups_ipv6)/sizeof(char*); + } +#endif + n=n4+n6; + if (n==0) + return 1; + + conf_mcast_groups=malloc(sizeof(char*)*n); + if (!conf_mcast_groups) + return 0; + memset(conf_mcast_groups,0,n*sizeof(char*)); + + int ctr=0; + int i; + for(i=0; i. +*/ + +#ifndef __CONF_H +#define __CONF_H + +#include +#include +#include +#include +#include +#include + + +#include "capwap.h" + +#ifndef CONF_DEFAULT_ACNAME + #define CONF_DEFAULT_ACNAME "AC" +#endif + +#ifndef CONF_DEFAULT_MAXWTPS + #define CONF_DEFAULT_MAXWTPS 200 +#endif + +#ifndef CONF_DEFAULT_LOGFILENAME + #define CONF_DEFAULT_LOGFILENAME NULL +#endif + +#ifndef CONF_DEFAULT_CONFIGFILENAME + #define CONF_DEFAULT_CONFIGFILENAME "ac.conf" +#endif + +#ifndef CONF_DEFAULT_VENDOR_ID + #define CONF_DEFAULT_VENDOR_ID 11591 /* Free Software Foundation */ +#endif + +#ifndef CONF_DEFAULT_SOFTWARE_VERSION + #define CONF_DEFAULT_SOFTWARE_VERSION "AC-Tube 0.01" +#endif + +#ifndef CONF_DEFAULT_HARDWARE_VERSION + #define CONF_DEFAULT_HARDWARE_VERSION "Linux/X86" +#endif + +#ifndef CONF_DEFAULT_CONTROL_PORT + #define CONF_DEFAULT_CONTROL_PORT CAPWAP_CONTROL_PORT +#endif + + +extern char * conf_acname; +extern int conf_acname_len; +extern long conf_max_wtps; +extern char * conf_logfilename; +extern struct sockaddr_storage * conf_salist; +extern int conf_salist_len; +extern long conf_vendor_id; +extern char * conf_hardware_version; +extern char * conf_software_version; +extern char ** conf_listen_addrs; +extern int conf_listen_addrs_len; + +extern struct sockaddr * conf_ac_ips; +extern int conf_ac_ips_len; + + +extern int read_config(const char * filename); +extern cfg_bool_t conf_ignore_wtp_source_port; +extern char * conf_control_port; + +extern char * conf_dtls_psk; + +extern char ** conf_mcast_groups; +extern int conf_mcast_groups_len; + +extern char ** conf_bcast_addrs; +extern int conf_bcast_addrs_len; + +extern long conf_debug_level; + +#endif diff --git a/src/ac/db.c b/src/ac/db.c new file mode 100644 index 00000000..5ba7ec1f --- /dev/null +++ b/src/ac/db.c @@ -0,0 +1,35 @@ + +#include + + + + +void test_db() +{ +// A prepered statement for fetching tables + sqlite3_stmt *stmt; +// +// // Create a handle for database connection, create a pointer to sqlite3 + sqlite3 *handle; + int rc = sqlite3_open("ac.sqlite3",&handle); + + if ( rc ) + { + perror("sqlite"); + printf("Database failed\n"); + + } + + printf ("DB RC: %i\n",rc); + + char cmd[100] = "xCREATE TABLE IF NOT EXISTS aclist (uname TEXT PRIMARY KEY,pass TEXT NOT NULL,activated INTEGER)"; + + rc = sqlite3_exec(handle,cmd,0,0,0); + + printf("CT RC: %i\n",rc); + const char *em = sqlite3_errmsg(handle); + printf("ErrMsg: %s\n",em); + return ; + + +} diff --git a/src/ac/socklist.c b/src/ac/socklist.c new file mode 100644 index 00000000..d948f979 --- /dev/null +++ b/src/ac/socklist.c @@ -0,0 +1,341 @@ +/* + This file is part of actube. + + actube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "cw_log.h" +#include "sock.h" + + +#include "socklist.h" + + +struct socklistelem * socklist=0; +int socklist_len; +static pthread_mutex_t socklist_mutex; +static int socklist_wtpcount=0; + + +int socklist_init() +{ + + if (pthread_mutex_init(&socklist_mutex,NULL)) + return 0; + + + socklist = malloc(sizeof(struct socklistelem) * SOCKLIST_SIZE); + memset(socklist,0,sizeof(struct socklistelem)*SOCKLIST_SIZE); + if (!socklist){ + cw_log(LOG_ERR,"Fatal error while initializing socklist: %s",strerror(errno)); + return 0; + } + + return 1; + +} + +void socklist_lock() +{ + pthread_mutex_lock(&socklist_mutex); +} + +void socklist_unlock() +{ + pthread_mutex_unlock(&socklist_mutex); +} + + +void socklist_destroy() +{ + int i; + for(i=0; isa_family!=sn.ss_family) + continue; + + if (bestsockfd == -1) + bestsockfd = socklist[i].sockfd; + + if (!bc) + return bestsockfd; + + struct sockaddr_storage bcaddr; + + if (!sock_getbroadcastaddr((struct sockaddr*)&sn,(struct sockaddr*)&bcaddr)) + continue; + + if (sock_cmpaddr((struct sockaddr*)&bcaddr,sa,0)) + continue; + + bestsockfd = socklist[i].sockfd; + + + } + return bestsockfd; +} + +void socklist_add_connection(int index) +{ + socklist_lock(); + socklist[index].wtpcount++; + socklist_wtpcount++; + socklist_unlock(); +} + +void socklist_del_connection(int index) +{ + socklist_lock(); + socklist[index].wtpcount--; + socklist_wtpcount--; + socklist_unlock(); +} + + + +int socklist_add_multicast(const char * addr, const char * port) +{ + + struct addrinfo hints; + struct addrinfo * res,*res0; + memset(&hints,0,sizeof(hints)); + + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = PF_UNSPEC; + hints.ai_flags=AI_PASSIVE; + + int rc = getaddrinfo(addr,port,&hints,&res0); + if (rc!=0) { + cw_log(LOG_ERR,"Can't bind multicast address '%s': %s",addr,gai_strerror(rc)); + return 0; + } + + for(res=res0; res; res=res->ai_next){ + struct sockaddr *sa = res->ai_addr; + int sockfd = socket(res->ai_addr->sa_family, SOCK_DGRAM, 0); + /* create socket */ + if (sockfd==-1){ + cw_log(LOG_ERR,"Can't create multicast socket: %",strerror(errno)); + continue; + } + + + /* bind address */ + if ( bind(sockfd,sa,sock_addrlen(sa)) < 0) { + close(sockfd); + cw_log(LOG_ERR,"Can't bind multicast %s: %s",addr,strerror(errno)); + continue; + } + + /* use setsockopt() to request that the kernel joins a multicast group */ + void *opt; + int optlen; + if (res->ai_addr->sa_family == AF_INET){ + + struct ip_mreq mreq; + memset(&mreq,0,sizeof(mreq)); + struct sockaddr_in * sain = (struct sockaddr_in*)res->ai_addr; + mreq.imr_multiaddr.s_addr=sain->sin_addr.s_addr; + mreq.imr_interface.s_addr=htonl(INADDR_ANY); + opt = &mreq; + optlen=sizeof(mreq); + + char sinin[100]; + sock_addrtostr((struct sockaddr*)sain,sinin,100); + + if (setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,opt,optlen) < 0) { + close(sockfd); + cw_log(LOG_ERR,"Can't add multicast membership %s: %s",addr,strerror(errno)); + continue; + } + + } + if (res->ai_addr->sa_family == AF_INET6){ + struct ipv6_mreq mreq; + memset(&mreq,0,sizeof(mreq)); + struct sockaddr_in6 * sain6 = (struct sockaddr_in6*)res->ai_addr; +// mreq.ipv6mr_multiaddr.s_addr=sain->sin_addr.s_addr; + memcpy(&mreq.ipv6mr_multiaddr.s6_addr,&sain6->sin6_addr.s6_addr,sizeof(sain6->sin6_addr.s6_addr)); +// int si = sizeof(sain6->sin6_addr.s6_addr); + +// int i = sain6->sin6_addr.s6_addr; + mreq.ipv6mr_interface=0; //htonl(INADDR_ANY); + opt = &mreq; + optlen=sizeof(mreq); + if (setsockopt(sockfd,IPPROTO_IPV6,IPV6_JOIN_GROUP,opt,optlen) < 0) { + close(sockfd); + cw_log(LOG_ERR,"Can't join multicast group %s: %s",addr,strerror(errno)); + continue; + } + } + + int rfd = find_reply_socket(sa,0); + + socklist[socklist_len].sockfd=sockfd; + socklist[socklist_len].reply_sockfd=rfd; + socklist[socklist_len].type=SOCKLIST_BCASTMCAST_SOCKET; + socklist[socklist_len].family=sa->sa_family; + + socklist_len++; + + cw_log(LOG_INFO,"Bound to multicast group: %s (fd=%i,r:%i)",addr,sockfd,rfd); + } + + freeaddrinfo(res0); + return 1; +} + + +int socklist_add_unicast(const char *addr, const char * port) +{ + struct addrinfo hints; + struct addrinfo * res,*res0; + memset(&hints,0,sizeof(hints)); + + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = PF_UNSPEC; + hints.ai_flags=AI_PASSIVE; + + int rc = getaddrinfo(addr,port,&hints,&res0); + if (rc!=0) { + cw_log(LOG_ERR,"Can't bind multicast address '%s': %s",addr,gai_strerror(rc)); + return 0; + } + + for(res=res0; res; res=res->ai_next){ + struct sockaddr *sa = res->ai_addr; + int sockfd = socket(res->ai_addr->sa_family, SOCK_DGRAM, 0); + /* create socket */ + if (sockfd==-1){ + cw_log(LOG_ERR,"Can't create unicast socket: %",strerror(errno)); + continue; + } + + /* bind address */ + if ( bind(sockfd,sa,sock_addrlen(sa)) < 0) { + close(sockfd); + cw_log(LOG_ERR,"Can't bind unicast socket %s: %s",addr,strerror(errno)); + continue; + } + + + socklist[socklist_len].sockfd=sockfd; + socklist[socklist_len].reply_sockfd=sockfd; + socklist[socklist_len].family=sa->sa_family; + socklist[socklist_len].type=SOCKLIST_UNICAST_SOCKET; + + socklist_len++; + cw_log(LOG_INFO,"Bound to: %s (%i)\n",addr,sockfd); + } + + freeaddrinfo(res0); + return 1; +} + +int socklist_add_broadcast(const char *addr, const char * port) +{ + struct addrinfo hints; + struct addrinfo * res,*res0; + memset(&hints,0,sizeof(hints)); + + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = PF_UNSPEC; + hints.ai_flags=AI_PASSIVE; + + + int rc = getaddrinfo(addr,port,&hints,&res0); + if (rc!=0) { + cw_log(LOG_ERR,"Can't bind broadcast address '%s': %s",addr,gai_strerror(rc)); + return 0; + } + + int sockfd; + for(res=res0; res; res=res->ai_next){ + + struct sockaddr *sa = res->ai_addr; + sockfd = socket(res->ai_addr->sa_family, SOCK_DGRAM, 0); + + /* create socket */ + if (sockfd==-1){ + cw_log(LOG_ERR,"Can't create broadcast socket: %",strerror(errno)); + continue; + } + +#ifdef IP_BINDANY + struct sockaddr_in * sain = (struct sockaddr_in*)sa; + if (sain->sin_addr.s_addr==INADDR_BROADCAST ){ + int opt=1; + if (setsockopt(sockfd, IPPROTO_IP, IP_BINDANY, &opt, sizeof(opt))){ + cw_log(LOG_ERR,"Can't set sockopt IP_BIND_ANY: %s",strerror(errno)); + continue; + }; + } +#endif + + /* bind address */ + if ( bind(sockfd,sa,sock_addrlen(sa)) < 0) { + close(sockfd); + sockfd=-1; + cw_log(LOG_ERR,"Can't bind broadcast %s: %s",addr,strerror(errno)); + continue; + } + + + int rfd = find_reply_socket(sa,1); + + socklist[socklist_len].sockfd=sockfd; + socklist[socklist_len].reply_sockfd=rfd; + socklist[socklist_len].type=SOCKLIST_BCASTMCAST_SOCKET; + socklist[socklist_len].family=sa->sa_family; + socklist_len++; + + cw_log(LOG_INFO,"Bound to broadcast: %s (%i) (R:%i)\n",addr,sockfd,rfd); + } + + freeaddrinfo(res0); + return 1; +} + + diff --git a/src/ac/socklist.h b/src/ac/socklist.h new file mode 100644 index 00000000..ad5d7749 --- /dev/null +++ b/src/ac/socklist.h @@ -0,0 +1,51 @@ +/* + This file is part of actube. + + actube 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 . + +*/ + +#ifndef __SOCKLIST_H +#define __SOCKLIST_H + +#define SOCKLIST_SIZE 32 + +enum { + SOCKLIST_UNICAST_SOCKET, + SOCKLIST_BCASTMCAST_SOCKET +}; + +struct socklistelem{ + int sockfd; + int reply_sockfd; + int type; + int family; + int wtpcount; +}; + + +extern int socklist_add_multicast(const char * addr, const char * port); +extern int socklist_add_unicast(const char *addr, const char * port); +extern int socklist_add_broadcast(const char *addr, const char * port); +extern int socklist_init(); +extern void socklist_destroy(); +extern struct socklistelem * socklist; +extern int socklist_len; +extern void socklist_lock(); +extern void socklist_unlock(); +void socklist_add_connection(int index); +void socklist_del_connection(int index); + + +#endif diff --git a/src/ac/wtplist.c b/src/ac/wtplist.c new file mode 100644 index 00000000..5cf1f3e7 --- /dev/null +++ b/src/ac/wtplist.c @@ -0,0 +1,149 @@ +/* + This file is part of actube. + + actube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include +#include +#include + +#include +#include +#include + + +#define MAX_WTPS 200 + +#include + +#include "wtplist.h" +#include "conn.h" +#include "sock.h" + + +#include "conf.h" +#include "cw_log.h" + +/* +static struct wtpman ** wtplist = 0; +static pthread_mutex_t wtplist_mutex; + +static int max_wtp_connections; +*/ + + +static struct connlist * connlist; + + +int wtplist_init() +{ + + connlist = connlist_create(0); + if (!connlist) + return 0; + + return 1; +} + +void wtplist_lock() +{ + connlist_lock(connlist); + +} + +void wtplist_unlock() +{ + connlist_unlock(connlist); +} + + +void wtplist_destroy() +{ + connlist_destroy(connlist); + +/* if (wtplist) + free (wtplist); + pthread_mutex_destroy(&wtplist_mutex); +*/ +} + + +struct wtpman * wtplist_get(const struct sockaddr * addr) +{ + + struct conn * conn = connlist_get(connlist,addr); + if (!conn) + return 0; + return conn->data; + +/* + int i; + for (i=0; iconn->addr,addr,1)) + continue; + struct wtpman * wtpman = wtplist[i]; + return wtpman; + + } + return NULL; +*/ +} + + +struct wtpman * wtplist_add(struct wtpman * wtpman) +{ + wtpman->conn->data=wtpman; + return connlist_add(connlist,wtpman->conn); + + +/* + int i; + for (i=0; iconn); + return; + +/* + printf("Remove wtpman %p\n",wtpman); + int i; + for (i=0; i + +#include "wtpman.h" + +extern int wtplist_init(); +extern void wtplist_destroy(); + +extern struct wtpman * wtplist_get(const struct sockaddr * addr); +extern struct wtpman * wtplist_add(struct wtpman * wtpman); +extern void wtplist_remove(struct wtpman * wtpman); +extern void wtplist_lock(); +extern void wtplist_unlock(); + + +#endif diff --git a/src/ac/wtpman.c b/src/ac/wtpman.c new file mode 100644 index 00000000..5da0e38c --- /dev/null +++ b/src/ac/wtpman.c @@ -0,0 +1,286 @@ +#include +#include +#include +#include + +#include + +#include "wtplist.h" + +#include "capwap.h" +#include "socklist.h" + +#include "conn.h" +#include "wtpman.h" +#include "conf.h" +#include "cw_log.h" + +#include "dtls.h" + + + +#include "conf.h" + + + + +#include + +#include "capwap.h" + + + +ACIPLIST * get_aciplist(); +struct ac_info * get_acinfo(); + + +static void process_discovery(struct wtpman * wtpman, struct cwrmsg * cwrmsg) +//uint8_t * hdr, uint8_t *msg, int len) +{ + printf("process_discovery called\n"); + printf("cwmsg: %p\n",cwrmsg); + printf("Message Type: %p\n",&cwrmsg->type); + printf("Message Type: %d\n",cwrmsg->type); + printf("WBID %d\n",cwrmsg->wbid); + + switch (cwrmsg->type){ + case CWMSG_DISCOVERY_REQUEST: + printf ("got a discovery requesti DISC\n"); + printf("MSGELEMS: %p\n",cwrmsg->msgelems); + printf("Seqnum %d\n",cwrmsg->seqnum); + printf("RIIIID: %d\n",cwrmsg->rid); + struct radioinfo radioinfo; + radioinfo.rid = cwrmsg->rid; + radioinfo.rmac = cwrmsg->rmac; + struct ac_info acinfo; +// capwap_init_acinfo(&acinfo); + process_discovery_request(&wtpman->wtpinfo,cwrmsg->msgelems,cwrmsg->msgelems_len); + + wtpinfo_print(&wtpman->wtpinfo); + + // struct radioinfo radioinfo; + cwsend_discovery_response(wtpman->conn,cwrmsg->seqnum,&radioinfo,&acinfo,&wtpman->wtpinfo); + break; + case CWMSG_JOIN_REQUEST: + printf ("Join message!!!!!!!!!!!!!!!!\n"); + process_join_request(&wtpman->wtpinfo,cwrmsg->msgelems,cwrmsg->msgelems_len); + wtpinfo_print(&wtpman->wtpinfo); + + exit(1); + break; + default: + printf ("Unknown message\n"); + exit(1); + break; + + } + + +} + +static void wtpman_remove(struct wtpman * wtpman) +{ + wtplist_lock(); + wtplist_remove(wtpman); + wtplist_unlock(); + wtpman_destroy(wtpman); +} + +static void wtpman_run_discovery(void *arg) +{ + struct wtpman * wtpman = (struct wtpman *)arg; + + struct cwrmsg * cwrmsg; +// do { + cwrmsg = conn_get_message(wtpman->conn); +// }while (!cwrmsg); + + + if ( !cwrmsg) + { + wtpman_remove(wtpman); + return; + } + + if (cwrmsg->type==CWMSG_DISCOVERY_REQUEST){ + process_discovery_request(&wtpman->wtpinfo,cwrmsg->msgelems,cwrmsg->msgelems_len); + + + + struct radioinfo radioinfo; + radioinfo.rid = cwrmsg->rid; + radioinfo.rmac = cwrmsg->rmac; + struct ac_info * acinfo = get_acinfo(); + +// wtpinfo_print(&wtpman->wtpinfo); + + cwsend_discovery_response(wtpman->conn,cwrmsg->seqnum,&radioinfo,acinfo,&wtpman->wtpinfo); + } + + wtpman_remove(wtpman); +} + + +static void wtpman_run(void *arg) +{ + struct wtpman * wtpman = (struct wtpman *)arg; + struct cwrmsg * cwrmsg = conn_get_message(wtpman->conn); + + + if (socklist[wtpman->socklistindex].type != SOCKLIST_UNICAST_SOCKET){ + cw_log_debug0("Dropping connection to non-unicast socket"); + wtpman_remove(wtpman); + return; + } + + cw_log_debug0("Establishing DTLS connection"); +#ifdef WITH_DTLS + + if (!conf_dtls_psk){ + cw_log(LOG_ERR,"Cant' establish DTLS connection, no psk set in config file"); + wtpman_remove(wtpman); + return; + } + wtpman->conn->dtls_psk=conf_dtls_psk; + wtpman->conn->dtls_psk_len=strlen(conf_dtls_psk); + wtpman->conn->dtls_cipher=CAPWAP_CIPHER; + + if ( !dtls_accept(wtpman->conn) ){ + cw_log_debug0("Error establishing DTLS connection"); + wtpman_remove(wtpman); + return; + } +#endif + cw_log_debug0("DTLS Session established with"); + cwrmsg = conn_get_message(wtpman->conn); +// printf("Seqnum: %i\n",cwrmsg->seqnum); + + if (cwrmsg->type != CWMSG_JOIN_REQUEST){ + cw_log_debug0("Join request expected but got %i",cwrmsg->type); + wtpman_remove(wtpman); + return; + + } + process_join_request(&wtpman->wtpinfo,cwrmsg->msgelems,cwrmsg->msgelems_len); + + struct radioinfo radioinfo; + radioinfo.rid = cwrmsg->rid; + radioinfo.rmac = cwrmsg->rmac; + struct ac_info * acinfo = get_acinfo(); + +// printf("ACN: %s\n",acinfo->ac_name); + + int result_code = 1; + cwsend_join_response(wtpman->conn,cwrmsg->seqnum,result_code,&radioinfo,acinfo,&wtpman->wtpinfo); + + cw_log_debug0("WTP joined"); + + int msg_counter = 0; + while(1){ + struct cwrmsg * cwrmsg = conn_get_message(wtpman->conn); + if (!cwrmsg) { + msg_counter++; + if (msg_counter < CAPWAP_ECHO_INTERVAL *2 ) + continue; + + cw_log_debug0("WTP died"); + wtpman_remove(wtpman); + return; + } + + msg_counter=0; + + + if (cwrmsg->type = CWMSG_ECHO_REQUEST){ + cwsend_echo_response(wtpman->conn,cwrmsg->seqnum,wtpman->wtpinfo.radioinfo); + } + printf("Got msg: %i\n",cwrmsg->type); + + } + + + + +// process_discovery(wtpman,cwrmsg); + exit(0); + + + printf("Messag gote ssl\n"); + + printf("Precdeis sssl\n"); + + printf ("SEQNUM REC: %i\n",cwrmsg->seqnum); + + printf("procdis ende\n"); + + + exit(0); + + + + + while (1) + { + /* + sem_wait(&wtpman->q_sem); + int qrpos = wtpman->qrpos+1; + if (qrpos==WTPMAN_QSIZE) + qrpos=0; + wtpman->qrpos=qrpos; + + uint8_t * packet = wtpman->q[qrpos]+4; + int len = *( (uint32_t*)(wtpman->q[qrpos])); +*/ + uint8_t * packet = conn_q_get_packet(wtpman->conn); + int len = *( (uint32_t*)(packet)); + + +// conn_process_packet(wtpman->conn,packet+4,len); + free(packet); + } +} + +void wtpman_destroy(struct wtpman * wtpman) +{ + if ( wtpman->conn) + conn_destroy(wtpman->conn); + free (wtpman); +} + + + +struct wtpman * wtpman_create(int socklistindex,struct sockaddr * srcaddr) +{ + struct wtpman * wtpman; + wtpman = malloc(sizeof(struct wtpman)); + if (!wtpman) + return 0; + memset (wtpman,0,sizeof(struct wtpman)); + + int sockfd = socklist[socklistindex].reply_sockfd; + +// wtpman->conn=conn_create(sockfd,srcaddr,process_discovery,wtpman,100); + wtpman->conn=conn_create(sockfd,srcaddr,100); + if (!wtpman->conn){ + wtpman_destroy(wtpman); + return NULL; + } + + return wtpman; +} + + +void wtpman_addpacket(struct wtpman * wtpman,uint8_t *packet,int len) +{ + conn_q_add_packet(wtpman->conn,packet,len); +} + + + +void wtpman_start(struct wtpman * wtpman,int dtlsmode) +{ + if ( dtlsmode ) + pthread_create (&wtpman->thread, NULL, (void *) &wtpman_run, (void *) wtpman); + else + pthread_create (&wtpman->thread, NULL, (void *) &wtpman_run_discovery, (void *) wtpman); +} diff --git a/src/ac/wtpman.h b/src/ac/wtpman.h new file mode 100644 index 00000000..530b25ad --- /dev/null +++ b/src/ac/wtpman.h @@ -0,0 +1,62 @@ +#ifndef __WTPMAN_H +#define __WTPMAN_H + +#include +#include +#include + +#include "capwap.h" +#include "fragman.h" + +#define WTPMAN_QSIZE 1024 + +struct wtpman{ +// struct sockaddr_storage addr; +// int sock; + pthread_t thread; + + /* packet queue */ +/* uint8_t * q[WTPMAN_QSIZE]; + int qrpos; + int qwpos; + sem_t q_sem; +*/ + struct conn * conn; + + /* fragment manager */ +// FRAGMAN * fragman; + + /* wtp data */ + uint8_t * wtp_name; + uint8_t * wtp_location; + uint8_t * session_id; + uint8_t wtp_mactype; + + struct wtpinfo wtpinfo; + +// pthread_mutex_t add_packet_mutex; + + int socklistindex; + int connected; + +}; + +struct wtp{ + + +}; + + +//extern void wtpman_run(void *arg); +extern struct wtpman * wtpman_create(); + +extern struct wtpman * wtpman_create(int socklistindex,struct sockaddr * srcaddr); + +extern void wtpman_addpacket(struct wtpman * wtpman,uint8_t *packet,int len); +extern void wtpman_destroy(struct wtpman * wtpman); +extern void wtpman_start(struct wtpman * wtpman,int dtlsmode); + + + + +#endif diff --git a/src/capwap/Makefile b/src/capwap/Makefile new file mode 100644 index 00000000..fbd61311 --- /dev/null +++ b/src/capwap/Makefile @@ -0,0 +1,161 @@ +#CC = gcc +AR = ar +SYSARCH := $(shell uname -m) + +ifndef ARCH + ARCH=$(SYSARCH) +endif + + + + +NAME=libcapwap.a + +SOCKOBJS=sock_create.o sock_copyaddr.o sock_strtoaddr.o sock_cmpaddr.o sock_addrlen.o \ + sock_receive.o sock_mwait.o sock_mreceive.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 + +LOGOBJS=cw_log.o \ + cw_log_debug.o \ + cw_log_tofile.o \ + cw_log_tosyslog.o + + +WTPINFOOBJS = wtpinfo_set_location.o \ + wtpinfo_print.o + +UTILOBJS=cw_setstr.o \ + cw_rand.o \ + cw_pseudo_rand.o \ + cw_foreach_msgelem.o \ + avltree.o \ + avltree_get.o \ + avltree_del_all.o \ + avltree_foreach.o \ + stravltree.o + +#capwap_parse_ctrlhdr.o \ + +CAPWAPOBJS= \ + cwmsg_init.o \ + cwmsg_init_echo_request.o \ + cwmsg_addelem.o \ + cwmsg_addelem_ac_descriptor.o \ + cwmsg_addelem_wtp_descriptor.o \ + cwmsg_addelem_ctrl_ip_addrs.o \ + cwmsg_addelem_wtp_radio_infos.o \ + cwmsg_addelem_wtp_board_data.o \ + cwmsg_addelem_cw_local_ip_addr.o \ + cwmsg_addelem_mtu_discovery_padding.o \ + cwmsg_addelem_result_code.o \ + cwmsg_send.o \ + cwsend_discovery_response.o \ + cwread_discovery_response.o \ + cwsend_discovery_request.o \ + cwsend_join_request.o \ + cwsend_join_response.o \ + cwread_join_response.o \ + cwsend_echo_request.o \ + cwsend_echo_response.o \ + process_msgelems_discovery_request.o \ + process_discovery_request.o \ + process_join_request.o \ + wtpinfo_readelem_wtp_board_data.o \ + wtpinfo_readelem_wtp_mac_type.o \ + wtpinfo_readelem_wtp_radio_info.o \ + wtpinfo_readelem_wtp_descriptor.o \ + wtpinfo_readelem_discovery_type.o \ + wtpinfo_readelem_wtp_frame_tunnel_mode.o \ + wtpinfo_readelem_location_data.o \ + wtpinfo_readelem_wtp_name.o \ + wtpinfo_readelem_session_id.o \ + wtpinfo.o \ + aciplist.o \ + acinfo.o \ + acinfo_print.o + + +# cwmsg_set_control_header.o +# process_msgelems.o \ + + +DTLSOBJS= dtls_openssl.o \ + dtls_openssl_accept.o \ + dtls_openssl_connect.o \ + dtls_openssl_bio.o + + +CONNOBJS= conn.o \ + conn_send_packet.o \ + conn_send_cwmsg.o \ + conn_process_packet.o \ + conn_get_message.o \ + conn_q_add_packet.o \ + conn_q_get_packet.o \ + conn_q_recv_packet.o \ + conn_recv_packet.o \ + connlist.o + + + +FRAGOBJS=fragman.o + +OBJS=$(CONNOBJS) $(FRAGOBJS) $(SOCKOBJS) $(CAPWAPOBJS) $(WTPINFOOBJS) $(LOGOBJS) $(UTILOBJS) $(DTLSOBJS) +O:=$(OBJS); + +OBJS:=$(patsubst %.o,$(ARCH)/%.o,$(OBJS)) + +#CFLAGS = -Wall -g -O3 -D_REENTRANT -DWITH_IPV6 +CFLAGS = -Wall -g -O0 -D_REENTRANT -DWITH_IPV6 -DWITH_RMAC_SUPPORT + +CFLAGS += -DWITH_CW_LOG \ + -DWITH_CW_LOG_DEBUG \ + -DWITH_DTLS \ + + +#SRCS = $(OBJS:.o=.c) + +$(ARCH)/%.o:%.c + @mkdir -p $(ARCH) + @echo " CC "$< + @$(CC) -c $(CFLAGS) $< -o $@ + + +$(ARCH)/$(NAME) : $(OBJS) + @echo " AR $(ARCH)/$(NAME)" + @$(AR) rcs $(ARCH)/$(NAME) $(OBJS) +#$(OBJS) + +#.c.o: +# $(CC) -c $(CFLAGS) $< + +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) $(OBJS) + $(RM) $(DEPS) + + +clean_deps: + $(DEPS) + +deps: $(SRCS) + $(CC) -MD -E $(SRCS) $(CFLAGS) >/dev/null + +-include $(DEPS) diff --git a/src/capwap/acinfo.c b/src/capwap/acinfo.c new file mode 100644 index 00000000..c323d370 --- /dev/null +++ b/src/capwap/acinfo.c @@ -0,0 +1,166 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include +#include +#include +#include + +#include "capwap.h" +#include "cw_log.h" +#include "cw_util.h" + +#include "acinfo.h" + +int acinfo_readelem_ac_name(struct ac_info * acinfo,int type, uint8_t *msgelem, int len) +{ + if (type != CWMSGELEM_AC_NAME) + return 0; + cw_setstr(&acinfo->ac_name,msgelem,len); + return 1; +} + + +int acinfo_readelem_ac_descriptor(struct ac_info * acinfo,int type, uint8_t *msgelem, int len) +{ + if (type != CWMSGELEM_AC_DESCRIPTOR) + return 0; + + if (len<12) + return -1; + + uint32_t val; + + /* read stations and limit */ + val = ntohl(*((uint32_t*)msgelem)); + acinfo->stations = val>>16; + acinfo->limit = val&0xffff; + + + /* read active wtps and max wtps */ + val = ntohl(*((uint32_t*)(msgelem+4))); + acinfo->active_wtps = val>>16; + acinfo->max_wtps = val&0xffff; + + /* read active wtps and max wtps */ + val = ntohl(*((uint32_t*)(msgelem+8))); + acinfo->security = val >>24; + acinfo->rmac= (val >> 16)&0xff; + acinfo->dtls_policy=val&0xf; + + int sub=12; + int sublen; + while (sub>16; + + if (sub+sublen>len) + return -1; + + + switch (subtype){ + case 4: + cw_setstr(&acinfo->hardware_version,msgelem+sub,sublen); + break; + case 5: + cw_setstr(&acinfo->software_version,msgelem+sub,sublen); + break; + } + sub+=sublen; + + } + + + return 1; +} + + + + +int acinfo_readelem_ctrl_ip_addr(struct ac_info * acinfo, int type, uint8_t*msgelem,int len) +{ + switch (type){ + case CWMSGELEM_CONTROL_IPV4_ADDRESS: + { + if (len!=6) + return -1; + + if (!acinfo->aciplist) + return 1; + + + ACIP * acip = malloc(sizeof(ACIP)); + if (!acip) { + cw_log(LOG_ERR,"Can't allocate memory for acv4ip: %s",strerror(errno)); + return 1; + } + + struct sockaddr_in addr; + memcpy(&addr.sin_addr,msgelem,4); + addr.sin_family=AF_INET; + memcpy(&acip->ip,&addr,sizeof(addr)); + + acip->wtp_count = ntohs( * ((uint16_t*)(msgelem+4))); + aciplist_add(acinfo->aciplist,acip); + + return 1; + + } + case CWMSGELEM_CONTROL_IPV6_ADDRESS: + { + if (len!=18) + return -1; + + if (!acinfo->aciplist) + return 1; + + + ACIP * acip = malloc(sizeof(ACIP)); + if (!acip) { + cw_log(LOG_ERR,"Can't allocate memory for acv4ip: %s",strerror(errno)); + return 1; + } + + struct sockaddr_in6 addr; + memcpy(&addr.sin6_addr,msgelem,16); + addr.sin6_family=AF_INET6; + memcpy(&acip->ip,&addr,sizeof(addr)); + acip->wtp_count = ntohs( * ((uint16_t*)(msgelem+16))); + + aciplist_add(acinfo->aciplist,acip); + + return 1; + } + + } + + return 0; +} + + + diff --git a/src/capwap/acinfo.h b/src/capwap/acinfo.h new file mode 100644 index 00000000..cacc4440 --- /dev/null +++ b/src/capwap/acinfo.h @@ -0,0 +1,62 @@ +#ifndef __ACINFO_H +#define __ACINFO_H + + +#include +#include + +#include "avltree.h" + +struct acip{ + struct sockaddr_storage ip; + int wtp_count; +}; + +typedef struct acip ACIP; +typedef struct avltree ACIPLIST; + +ACIPLIST * aciplist_create(); +#define aciplist_destroy(l) avltree_destroy(l) +#define aciplist_add(l,elem) avltree_add(l,elem) +#define aciplist_foreach(l,callback,cbpriv) avltree_foreach(l,callback,cbpriv,1) + + +/* structure to hold info about an ac */ +struct ac_info{ + int stations; + int limit; + int active_wtps; + int max_wtps; + uint8_t * ac_name; + int ac_name_len; + int security; + int rmac; + int dtls_policy; + int vendor_id; + uint8_t * hardware_version; + uint8_t * software_version; +// const char * acname; + + struct sockaddr * salist; + int salist_len; + + ACIPLIST * aciplist; + uint8_t ecn_support; + + struct sockaddr_storage local_ip; + +}; + +typedef struct ac_info ACINFO; + +extern int acinfo_readelem_ac_name(struct ac_info * acinfo,int type, uint8_t *msgelem, int len); +extern int acinfo_readelem_ac_descriptor(struct ac_info * acinfo,int type, uint8_t *msgelem, int len); +extern int acinfo_readelem_ctrl_ip_addr(struct ac_info * acinfo, int type, uint8_t*msgelem,int len); +extern int acinfo_print(char *str,const struct ac_info *acinfo); + +#define acinfo_readelem_ecn_support(acinfo,type,msg,len) cw_readelem_ecn_support(&acinfo->ecn_support,type,msg,len) +#define acinfo_readelem_cw_local_ip_addr(acinfo,type,msg,len) cw_readelem_cw_local_ip_addr(&acinfo->local_ip,type,msg,len) + + +#endif + diff --git a/src/capwap/acinfo_print.c b/src/capwap/acinfo_print.c new file mode 100644 index 00000000..5d8889f1 --- /dev/null +++ b/src/capwap/acinfo_print.c @@ -0,0 +1,59 @@ +#include +#include + +#include "capwap.h" +#include "sock.h" + +#include "acinfo.h" + + +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\n",acinfo->hardware_version); + s+=sprintf(s,"\tSoftware version: %s\n",acinfo->software_version); + 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==2 ? "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; +} + + + diff --git a/src/capwap/aciplist.c b/src/capwap/aciplist.c new file mode 100644 index 00000000..dd0d3d2e --- /dev/null +++ b/src/capwap/aciplist.c @@ -0,0 +1,53 @@ +#include +#include + +#include +#include + +#include "acinfo.h" +#include "avltree.h" +#include "sock.h" + + +static int acip_cmp(const void *x1, const void *x2) +{ + struct acip * ip1 = (struct acip*)x1; + struct acip * ip2 = (struct acip*)x2; + + 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); +} + +ACIPLIST * aciplist_create() +{ + struct avltree *t = avltree_create(acip_cmp,acip_del); + return t; +} + + + diff --git a/src/capwap/avltree.c b/src/capwap/avltree.c new file mode 100644 index 00000000..172eec5e --- /dev/null +++ b/src/capwap/avltree.c @@ -0,0 +1,669 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include +#include + + +#include "avltree.h" + + +struct avltree * avltree_create(int (*cmp)(const void*,const void*),void(*del)(void*)) +{ + struct avltree * t = malloc(sizeof(struct avltree)); + if (!t) + return 0; + t->root=0; + t->count=0; + t->cmp=cmp; + t->del=del; + return t; +} + +struct avlnode * avlnode_create(void * data) +{ + struct avlnode * n = malloc(sizeof(struct avlnode)); + if(!n) + return 0; + + n->left=n->right=0; + n->bal=0; + n->data = data; + return n; +} + + +void avlnode_destroy(struct avltree *t,struct avlnode *n) +{ + if(t->del){ + t->del(n->data); + } + free(n); + t->count--; +} + + +static int avltree_add0(struct avltree *t, struct avlnode ** parent, void ** data) +{ +// struct avlnode * rn; + struct avlnode *tmp; + + struct avlnode * n = *parent; + int rc=t->cmp(*data,n->data); + + int bal; + if (rc==0){ + *data=n->data; + return 2; + } + + if (rc<0){ + if (n->left) + { + bal = avltree_add0(t,&n->left,data); + if (bal>1) + return bal; + + n->bal -=bal; + if (n->bal==0) + return 0; + + if (n->bal==-2){ + if (n->left->bal==-1){ + n->bal=0; + n->left->bal=0; + *parent=n->left; + tmp=n->left->right; + n->left->right=n; + n->left=tmp; + return 0; + } + if (n->left->bal==1){ + *parent=n->left->right; + if ((*parent)->bal==1) { + n->bal=0; + n->left->bal=-1; + } + else if ((*parent)->bal==-1){ + n->bal=1; + n->left->bal=0; + } + else{ + n->bal=0; + n->left->bal=0; + } + + (*parent)->bal=0; + n->left->right=(*parent)->left; + (*parent)->left=n->left; + tmp = (*parent)->right; + (*parent)->right=n; + n->left=tmp; + return 0; + + } + + //printf("!!!!left bal = %i\n",n->left->bal); + //exit(0); + + } + return bal; + + } + + /* n->left is 0 */ + n->left=avlnode_create(*data); + if (!n->left) + return 3; + + t->count++; + + if(n->right==0){ + n->bal=-1; + return 1; + } + + n->bal=0; + return 0; + + } + else{ + if (n->right){ + bal = avltree_add0(t,&n->right,data); + if(bal>1) + return bal; + + n->bal+=bal; + if (n->bal==0) + return 0; + + if (n->bal==2){ + if (n->right->bal==1){ + n->bal=0; + n->right->bal=0; + *parent=n->right; + tmp=n->right->left; + n->right->left=n; + n->right=tmp; + return 0; + } + else if(n->right->bal==-1){ + *parent=n->right->left; + + if ((*parent)->bal==-1) { + n->bal=0; + n->right->bal=1; + } + else if ((*parent)->bal==1){ + n->bal=-1; + n->right->bal=0; + } + else{ + n->bal=0; + n->right->bal=0; + } + + + + + + (*parent)->bal=0; + n->right->left=(*parent)->right; + (*parent)->right=n->right; + tmp = (*parent)->left; + (*parent)->left=n; + n->right=tmp; + return 0; + } + //printf("!!!!iright bal = %i\n",n->left->bal); + //exit(0); + + + } + return bal; + + } + + /* n->right is 0 */ + + n->right=avlnode_create(*data); + if (!n->right) + return 3; + + t->count++; + if(n->left==0){ + n->bal=1; + return 1; + } + n->bal=0; + return 0; + } +} + + + +void * avltree_add(struct avltree *t, void * data) +{ + if (t->root==0){ + t->root = avlnode_create(data); + if (t->root) + t->count++; + return t->root->data; + } + void * d = data; + int rc = avltree_add0(t,&t->root,&d); + + if (rc>3) + return 0; + + return d; +} + +static void rot_l(struct avlnode *n, struct avlnode **parent) +{ + struct avlnode *tmp; + *parent=n->right; + tmp=n->right->left; + n->right->left=n; + n->right=tmp; +} + + +static void rot_r(struct avlnode *n, struct avlnode **parent) +{ + struct avlnode *tmp; + *parent=n->left; + tmp=n->left->right; + n->left->right=n; + n->left=tmp; +} + + + + +/* + * Delete the node withe the highest value + * returns the rebalancing factor + */ + +/* +static int avltree_delete_hi(struct avlnode **parent, void **data) +{ + struct avlnode * n = *parent; + + if(n->right!=0){ + int bal = avltree_delete_hi(&n->right,data); + n->bal-=bal; + if (n->bal==-2){ + + // if (rotate_r(n,parent)) + // return 0; + } + + return bal; + } + + *parent=n->left; + *data = n->data; + if (n->left){ + free(n); + return 0; + } + free(n); + return 1; +} +*/ + +struct avltree * trrr; + +static void rot_rl(struct avlnode *n, struct avlnode **parent) +{ + struct avlnode * tmp; + *parent=n->right->left; + n->right->left=(*parent)->right; + (*parent)->right=n->right; + tmp = (*parent)->left; + (*parent)->left=n; + n->right=tmp; +} + +static void rot_lr(struct avlnode *n, struct avlnode **parent) +{ + struct avlnode * tmp; + *parent=n->left->right; + n->left->right=(*parent)->left; + (*parent)->left=n->left; + tmp = (*parent)->right; + (*parent)->right=n; + n->left=tmp; +} + + +static int adj_bal_l(struct avlnode *n, struct avlnode **parent) +{ + if (n->right->bal==1){ + n->bal=0; + n->right->bal=0; + rot_l(n,parent); + return 1; + } + else if(n->right->bal==0){ + n->bal=1; + n->right->bal=-1; + rot_l(n,parent); + return 0; + }else if(n->right->bal==-1){ +// int rb; + n->bal=0; + n->right->bal=0; +// rb = n->right->left->bal; + n->right->left->bal=0; + rot_rl(n,parent); + return 1; + } + +// printf("adj bal l not handled \n"); +// exit(0); + + return -11; /* that should never happen */ +} + +int adj_bal_r(struct avlnode *n, struct avlnode **parent) +{ + + if (n->left->bal==-1){ + n->bal=0; + n->left->bal=0; + rot_r(n,parent); + return 1; + } + else if(n->left->bal==0){ + n->bal=-1; + n->left->bal=1; + rot_r(n,parent); + return 0; + } + else if(n->left->bal==1){ +// int rb; + n->bal=0; + n->left->bal=0; +// rb = n->left->right->bal; + n->left->right->bal=0; + rot_lr(n,parent); + return 1; + } + +// printf("adj bal li left not handled \n"); +// exit(0); + return -11; /* that should never happen */ +} + + + + +static int avltree_del_lo(struct avlnode **parent, void **data) +{ + struct avlnode * n = *parent; + + if(n->left!=0){ + int bal = avltree_del_lo(&n->left,data); + n->bal+=bal; + if (n->bal==1){ + return 0; + } + if (n->bal!=2) + return bal; + adj_bal_l(n,parent); + return 0; + } + + /* found the lowest element */ + + *parent=n->right; + *data = n->data; + free (n); + return 1; + + + if (n->right){ + free(n); + return 1; + } + free(n); + return 1; + +} + + + + +int avltree_del0(struct avltree *t, struct avlnode **parent, void **data) +{ + struct avlnode * n = *parent; + int rc; + int bal; + + rc =t->cmp(*data,n->data); + + if (rc==0){ + if (n->right == 0 && n->left ==0){ + *parent=0; + avlnode_destroy(t,n); + return 1; + } + + if (n->right && n->left==0){ + *parent=n->right; + avlnode_destroy(t,n); + return 1; + + } + + if (n->left && n->right==0){ + avlnode_destroy(t,n); + *parent=n->left; + return 1; + + } + + /* node has two childs */ + + if (t->del){ + t->del(n->data); + } + t->count--; + bal = avltree_del_lo(&n->right,&n->data); + n->bal-= bal; + if (n->bal==-1) + return 0; + + if (n->bal != -2) + return bal; + + return adj_bal_r(n,parent); + + } + + if (rc<0){ + if (n->left) + { + bal = avltree_del0(t,&n->left,data); + if (bal==2) + return 2; + + n->bal+=bal; + if (n->bal==1) + return 0; + + if (n->bal!=2) + return bal; + + return adj_bal_l(n,parent); + } + return 2; /* not found */ + } + else { /* rc must be > 0 */ + if (n->right){ + bal = avltree_del0(t,&n->right,data); + if (bal==2) + return 2; + + n->bal-=bal; + if (n->bal==-1) + return 0; + + if (n->bal != -2) + return bal; + + return adj_bal_r(n,parent); + + + } + return 2; /* not found */ + + } + +} + +void * avltree_del(struct avltree *t, void *data) +{ + void *d = data; + int rc = avltree_del0(t,&t->root,&d); + if (rc==2) + return 0; + return data; +} + +/* +static int cmp(const void *k1,const void *k2) +{ + int x1 = *((int*)k1); + int x2 = *((int*)k2); + return x1-x2; +} +*/ + +//int data[]={10,37,60,10,5,35,36,26,3,11,18}; +//int data[] = {100,50,75}; +//int data[]={100,200,150,300,400}; +//int data[]={100,200,150,170,470}; +//int data[]={10,20,15,17,47,50,60,70,80}; +//int data[]={9,8,7,6,5,4,3,2,1,0}; + +//int data[]={10,37,60,10,5,35,19,26,3,11,18}; +//int data[]={0,11,14,33,37,20}; +//int data[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; +//int data[]={1,4,3,7,5,6,7,8,9,10}; +//int data[]={11,4,5,6,3,4,3,2,1,0}; +//int data[]={20,16,10,11,5,4,3,2,1,0}; + +/* +struct avlnode * ar[10000]; +int tpw = 80; + +static void print_tree0(struct avlnode * n,int d,int l,int r) +{ + int pos = l+(r-l)/2; + ar[d*tpw+pos]=n; + if (n->right) + print_tree0(n->right,d+1,l+(r-l)/2,r); + if(n->left) + print_tree0(n->left,d+1,l,r-(r-l)/2); +} + +void avltree_print(struct avlnode * n ) +{ + + int y; + int i=0; + for(i=0; i<10000; i++) + ar[i]=0; + + if (n==0){ + + printf("Empty Tree\n"); + return ; + } + + print_tree0(n,0,0,tpw); + for (i=0; i<10; i++) { + for (y=0; ydata),r->bal); + } + else{ + printf("."); + } + } + printf("\n"); + } + + +} + + + +void walk(struct avlnode *n) +{ + if (n == 0) + return; + walk(n->left); + int x = *((int*)(n->data)); + printf("VAL: %i\n",x); + walk(n->right); +// x = *((int*)(n->data)); +// printf("VALR: %i\n",x); + +} + +*/ + +void avltree_destroy(struct avltree *t) +{ + avltree_del_all(t); + free (t); +} + + +//#include + + + + + + + + + +/* +//int data[]={5,1,9,7,0,10,8,0,4,3}; +//int data[]={50,10,90,70,00,100,80,00,40,30,1,2,3}; +int data[]={10,20,30,45,1,50,11,51,60,70,80,90,99,25,50,10,90,70,00,100,80,00,40,30,1,2,3}; + + +int main() +{ + struct avltree *t = avltree_create(cmp,0); + trrr=t; + printf("T: %p\n",t); + + srand(time(NULL)); + int i=0; + for (i=0; i<6; i++) + { + int r = rand()%0x3f; // % 0xiff; +// int r = rand(); //%0x3f; // % 0xiff; + + // r = data[7-i]; + r = data[i]; + int * dr = malloc(sizeof(int)); + *dr = r; + + + printf("Insert %i\n",*dr); + + void * d = avltree_insert(t,dr); + printf("After insert %i\n",r); + print_tree(t->root); + + if (d!=dr){ +// printf("exists\n"); + } + + + } + + printf("Here it is\n"); + print_tree(t->root); +// walk(t->root); + void * da; + + int x = 110; + +// void * drc = avltree_delete(t,&x); + avltree_delete_all(t); +// printf("Delete 110 rc = %p\n",drc); + print_tree(t->root); + printf("Count: %i\n",t->count); + return 0; +} + + + +*/ diff --git a/src/capwap/avltree.h b/src/capwap/avltree.h new file mode 100644 index 00000000..8edbe532 --- /dev/null +++ b/src/capwap/avltree.h @@ -0,0 +1,64 @@ +/* + 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 . + +*/ + +/* + * yet another avl tree implementation! + */ + +#ifndef __AVLTREE_H +#define __AVLTREE_H + +struct avlnode{ + void * data; + struct avlnode * left; + struct avlnode * right; + int bal; +}; + + +struct avltree{ + struct avlnode * root; + int (*cmp)(const void*,const void*); + void(*del)(void*); + int count; +}; + +void avlnode_destroy(struct avltree *t,struct avlnode *n); + +struct avltree * avltree_create(int (*cmp)(const void*,const void*),void(*del)(void*)); +void avltree_destroy(struct avltree *t); + +void avltree_del_all(struct avltree *t); +void * avltree_del(struct avltree *t, void *data); +void * avltree_add(struct avltree *t, void *data); +void * avltree_get(struct avltree *t ,void *data); + +extern int avltree_foreach_lr(struct avlnode *n, int (*callback)(void *,void *),void *cbpriv); +extern int avltree_foreach_rl(struct avlnode *n, int (*callback)(void *,void *),void *cbpriv); +extern void avltree_foreach(struct avltree *t, int (*callback)(void *,void*),void *cbpriv,int dir); + + + +#define avltree_find(t,d) avltree_get(t,d) +#define avltree_insert(t,d) avltree_add(t,d) +#define avltree_walk(t,dir) avltree_foreach(t,dir) + + +#endif + + diff --git a/src/capwap/avltree.old.c b/src/capwap/avltree.old.c new file mode 100644 index 00000000..661c12db --- /dev/null +++ b/src/capwap/avltree.old.c @@ -0,0 +1,564 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include +#include + + +#include "avltree.h" + +/* +struct avlnode{ + void * data; + struct avlnode * left; + struct avlnode * right; + int bal; +}; + +struct avltree{ + struct avlnode * root; + int (*cmp)(const void*,const void*); + void(*del)(void*); + int count; +}; + +*/ + + +struct avltree * avltree_create(int (*cmp)(const void*,const void*),void(*del)(void*)) +{ + struct avltree * t = malloc(sizeof(struct avltree)); + if (!t) + return 0; + t->root=0; + t->count=0; + t->cmp=cmp; + t->del=del; + return t; +} + +struct avlnode * avlnode_create(void * data) +{ + struct avlnode * n = malloc(sizeof(struct avlnode)); + if(!n) + return 0; + + n->left=n->right=0; + n->bal=0; + n->data = data; + return n; +} + + +int avltree_insert0(struct avltree *t, struct avlnode ** parent, void ** data) +{ +// struct avlnode * rn; + struct avlnode *tmp; + + struct avlnode * n = *parent; + int rc=t->cmp(*data,n->data); + + int bal; + if (rc==0){ + *data=n->data; + return 2; + } + + if (rc<0){ + if (n->left) + { + bal = avltree_insert0(t,&n->left,data); + if (bal>1) + return bal; + printf("Left ret bal %i\n",bal); + + n->bal -=bal; + if (n->bal==0) + return 0; + + if (n->bal==-2){ + if (n->left->bal==-1){ + n->bal=0; + n->left->bal=0; + *parent=n->left; + tmp=n->left->right; + n->left->right=n; + n->left=tmp; +// printf("Left rot a\n"); +// print_tree(t->root); + return 0; + } + if (n->left->bal==1){ + printf("BUMBUMBUM\n"); + print_tree(t->root); +// n->bal=0; +// n->left->bal=0; + *parent=n->left->right; + if ((*parent)->bal==1) { + n->bal=0; + n->left->bal=-1; + } + else{ + n->bal=1; + n->left->bal=0; + } + + (*parent)->bal=0; + + n->left->right=(*parent)->left; + (*parent)->left=n->left; + tmp = (*parent)->right; + (*parent)->right=n; + n->left=tmp; + printf("Left rot b\n"); +// print_tree(t->root); + return 0; + + } + + print_tree(t->root); + printf("!!!!left bal = %i\n",n->left->bal); + exit(0); + + } + return bal; + + } + + /* n->left is 0 */ + n->left=avlnode_create(*data); + if (!n->left) + return 3; + + t->count++; + + if(n->right==0){ + n->bal=-1; + return 1; + } + + n->bal=0; + return 0; + + } + else{ + if (n->right){ + bal = avltree_insert0(t,&n->right,data); + if(bal>1) + return bal; + + printf("Right ret bal %i\n",bal); + n->bal+=bal; + if (n->bal==0) + return 0; + + if (n->bal==2){ + if (n->right->bal==1){ + n->bal=0; + n->right->bal=0; + *parent=n->right; + tmp=n->right->left; + n->right->left=n; + n->right=tmp; +// printf("Right rot a\n"); +// print_tree(t->root); + return 0; + } + else { + printf("Right rot b before\n"); +// print_tree(t->root); + n->bal=0; + n->right->bal=0; + *parent=n->right->left; + (*parent)->bal=0; + n->right->left=(*parent)->right; + (*parent)->right=n->right; + tmp = (*parent)->left; + (*parent)->left=n; + n->right=tmp; +// printf("Right rot b\n"); +// print_tree(t->root); + return 0; + } + + } + return bal; + + } + + /* n->right is 0 */ + n->right=avlnode_create(*data); + if (!n->right) + return 3; + + t->count++; + if(n->left==0){ + n->bal=1; + return 1; + } + n->bal=0; + return 0; + } +} + + + +void * avltree_insert(struct avltree *t, void * data) +{ + + if (t->root==0){ + t->root = avlnode_create(data); + return t->root->data; + } + void * d = data; + int rc = avltree_insert0(t,&t->root,&d); + + if (rc>3) + return 0; + + return d; +// printf("RC %i\n",rc); +} + + + +static int rotate_r(struct avlnode *n, struct avlnode **parent) +{ + if (n->bal!=-2) + return 0; + + struct avlnode * tmp; + + if (n->bal==-1){ + n->bal=0; + n->left->bal=0; + *parent=n->left; + tmp=n->left->right; + n->left->right=n; + n->left=tmp; + return 1; + } + + else /* if (n->left->bal==1)*/ { + n->bal=0; + n->left->bal=0; + *parent=n->left->right; + n->left->right=(*parent)->left; + (*parent)->left=n->left; + tmp = (*parent)->right; + (*parent)->right=n; + n->left=tmp; + return 1; + } + +} + + +static int rotate_l(struct avlnode *n, struct avlnode **parent) +{ + if (n->bal!=2) + return 0; + + struct avlnode * tmp; + if (n->right->bal==1){ + n->bal=0; + n->right->bal=0; + *parent=n->right; + tmp=n->right->left; + n->right->left=n; + n->right=tmp; + return 1; + } + else { /* n->bal musst be -1 */ + n->bal=0; + n->right->bal=0; + *parent=n->right->left; + n->right->left=(*parent)->right; + (*parent)->right=n->right; + tmp = (*parent)->left; + (*parent)->left=n; + n->right=tmp; + return 1; + } + +} + + + +/* + * Delete the node withe the highest value + * returns the rebalancing factor + */ +static int avltree_delete_hi(struct avlnode **parent, void **data) +{ + struct avlnode * n = *parent; + + if(n->right!=0){ + int bal = avltree_delete_hi(&n->right,data); + n->bal-=bal; + if (rotate_r(n,parent)) + return 0; + + return bal; + } + + *parent=n->left; + *data = n->data; + if (n->left){ + free(n); + return 0; + } + free(n); + return 1; +} + + +static int avltree_delete_lo(struct avlnode **parent, void **data) +{ + struct avlnode * n = *parent; + + if(n->left!=0){ + int bal = avltree_delete_lo(&n->left,data); + n->bal+=bal; + if (rotate_l(n,parent)) + return 0; + + return bal; + } + + *parent=n->right; + *data = n->data; + if (n->right){ + free(n); + return 0; + } + free(n); + return 1; + +} + + + + +int avltree_delete0(struct avltree *t, struct avlnode **parent, void **data) +{ + struct avlnode * n = *parent; + int rc; + + rc =t->cmp(*data,n->data); + + if (rc==0){ + if (n->right == 0 && n->left ==0){ + printf("My case a!\n"); + *parent=0; + return 1; + } + + + if (n->right && n->left==0){ + printf("My case b!\n"); + *parent=n->right; + return 1; + + } + + if (n->left && n->right==0){ + printf("My case c!\n"); + + *parent=n->left; + return 1; + + } + + + + } + + int bal; + if (rc<0){ + if (n->left) + { + bal = avltree_delete0(t,&n->left,data); + printf("Ballla = %i\n",bal); + n->bal+=bal; + if (!rotate_l(n,parent)) + return bal; + return bal; + + + } + } + else { + if (n->right){ + printf("Bolla\n"); + bal = avltree_delete0(t,&n->right,data); + n->bal-=bal; + if (!rotate_r(n,parent)) + return bal; + return bal; + + } + + } + + + return 0; + +} + +void * avltree_delete(struct avltree *t, void *data) +{ + void *d = data; + + printf("deletelel %p\n",d); + + avltree_delete0(t,&t->root,&d); + return 0; +} + +static int cmp(const void *k1,const void *k2) +{ + int x1 = *((int*)k1); + int x2 = *((int*)k2); + return x1-x2; +} + +int data[]={10,37,60,10,5,35,36,26,3,11,18}; +//int data[]={10,37,60,10,5,35,19,26,3,11,18}; +//int data[]={0,11,14,33,37,20}; +//int data[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; +//int data[]={1,4,3,7,5,6,7,8,9,10}; +//int data[]={11,4,5,6,3,4,3,2,1,0}; +//int data[]={20,16,10,11,5,4,3,2,1,0}; + +struct avlnode * ar[10000]; +int tpw = 100; + +void print_tree0(struct avlnode * n,int d,int l,int r) +{ + int pos = l+(r-l)/2; + ar[d*tpw+pos]=n; + if (n->right) + print_tree0(n->right,d+1,l+(r-l)/2,r); + if(n->left) + print_tree0(n->left,d+1,l,r-(r-l)/2); +} + +void print_tree(struct avlnode * n ) +{ + int y; + int i=0; + for(i=0; i<10000; i++) + ar[i]=0; + + if (n==0){ + + printf("Empty Tree\n"); + return 0; + } + + print_tree0(n,0,0,tpw); + for (i=0; i<10; i++) { + for (y=0; ydata),r->bal); + } + else{ + printf("."); + } + } + printf("\n"); + } + + +} + +void walk(struct avlnode *n) +{ + if (n == 0) + return; + walk(n->left); + int x = *((int*)(n->data)); + printf("VAL: %i\n",x); + walk(n->right); +// x = *((int*)(n->data)); +// printf("VALR: %i\n",x); + +} + + +#include + +int main() +{ + struct avltree *t = avltree_create(cmp,0); + + printf("T: %p\n",t); + + srand(time(NULL)); + int i=0; + for (i=0; i<7; i++) + { + int r = rand()%0x3f; // % 0xiff; + + r = data[7-i]; + int * dr = malloc(sizeof(int)); + *dr = r; + + + printf("Insert %i\n",*dr); + + void * d = avltree_insert(t,dr); + printf("After insert %i\n",r); + print_tree(t->root); + + if (d!=dr){ +// printf("exists\n"); + } + + + } + + print_tree(t->root); + walk(t->root); + void * da; + +// avltree_delete(t,&data[4]); + avltree_delete_hi(&t->root,&da); +// printf("after del\n"); +// print_tree(t->root); + + +// avltree_delete(t,&data[7]); + avltree_delete_lo(&t->root,&da); +// printf("after del\n"); +// print_tree(t->root); + + + +// avltree_delete(t,&data[5]); + avltree_delete_lo(&t->root,&da); +// printf("after del\n"); +// print_tree(t->root); + return 0; +} + + + + diff --git a/src/capwap/avltree_del_all.c b/src/capwap/avltree_del_all.c new file mode 100644 index 00000000..7f0d5927 --- /dev/null +++ b/src/capwap/avltree_del_all.c @@ -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 . + +*/ + +#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; +} + + diff --git a/src/capwap/avltree_foreach.c b/src/capwap/avltree_foreach.c new file mode 100644 index 00000000..d9889d99 --- /dev/null +++ b/src/capwap/avltree_foreach.c @@ -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 . + +*/ + +#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); + +} + +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); +} + diff --git a/src/capwap/avltree_get.c b/src/capwap/avltree_get.c new file mode 100644 index 00000000..eafdd28e --- /dev/null +++ b/src/capwap/avltree_get.c @@ -0,0 +1,37 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include "avltree.h" + + +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 0; +} + + diff --git a/src/capwap/capwap.h b/src/capwap/capwap.h new file mode 100644 index 00000000..3401521a --- /dev/null +++ b/src/capwap/capwap.h @@ -0,0 +1,338 @@ +/* + 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 . + +*/ + +#ifndef __CAPWAP_H +#define __CAPWAP_H + +#include +#include + +#include "conn.h" + +/* capwap version and iana number */ +#define CW_VERSION 0 +#define CWIANA_ENTERPRISE_NUMBER 13277 + + +/* ports */ +#define CAPWAP_CONTROL_PORT 5246 +#define CAPWAP_CONTROL_PORT_STR "5246" + + + + +/* transport header flags */ +#define CWTH_FLAGS_R1 0x01 /* bit 0 reserved 1 */ +#define CWTH_FLAGS_R2 0x02 /* bit 1 reserved 2 */ +#define CWTH_FLAGS_R3 0x04 /* bit 2 reserved 3 */ +#define CWTH_FLAGS_K 0x08 /* bit 3 Keep alive flag */ +#define CWTH_FLAGS_M 0x10 /* bit 4 MAC Adress field present*/ +#define CWTH_FLAGS_W 0x20 /* bit 5 wireless info present */ +#define CWTH_FLAGS_L 0x40 /* bit 6 last fragment */ +#define CWTH_FLAGS_F 0x80 /* bit 7 fragment */ +#define CWTH_FLAGS_T 0x100 /* bit 8 type of payload frame */ + +/* wireless binding ids */ +#define CWTH_WBID_RESERVED1 0 +#define CWTH_WBID_IEEE80211 1 +#define CWTH_WBID_RESERVED2 2 +#define CWTH_WBID_EPCGLOBAL 3 + + + + +/* generic macroto to isolate bits from a dword */ +#define CW_GET_DWORD_BITS(src,start,len) ((~(0xFFFFFFFF<> (32 - start - len))) + +/* macros to acces transport header values */ +#define CWTH_GET_PREAMBLE(th) (th[0]) +//(ntohl(((uint32_t*)th)[0]) >> 24) +#define CWTH_GET_FRAGID(th) ((ntohl((((uint32_t*)th)[1]) >> 16) & 0xffff)) +#define CWTH_GET_FRAGOFFSET(th) ((ntohl((((uint32_t*)th)[1]) >> 3) & 0x1fff)) +#define CWTH_GET_RID(th) ((ntohl((((uint32_t*)th)[0]) >> 14) & 0x1f)) +#define CWTH_GET_WBID(th) ((ntohl(((uint32_t*)th)[0]) >> 9) & 0x1f) +#define CWTH_GET_HLEN(th) ((ntohl(((uint32_t*)th)[0]) >> 19) & 0x1f) + +#define CAPWAP_PACKET_PREAMBLE (CW_VERSION<<4) +#define CAPWAP_DTLS_PACKET_PREAMBLE (CW_VERSION<<4|1) + +/* + * control header stuff + */ +struct capwap_ctrlhdr +{ + int msgtype; + int seqnum; + int flags; + uint8_t * msgelems; + int msgelemslen; +}; + + +//extern int capwap_parse_trnsprthdr(struct capwap_trnsprthdr * cwh,uint8_t *msg, int msglen); +//extern int capwap_parse_ctrlhdr(struct capwap_ctrlhdr * ch,uint8_t * msg, int len); + +/* CAPWAP message types as defined in RFC 5416 */ + +#define CWMSG_DISCOVERY_REQUEST 1 +#define CWMSG_DISCOVERY_RESPONSE 2 +#define CWMSG_JOIN_REQUEST 3 +#define CWMSG_JOIN_RESPONSE 4 + +/* Configuration Status Request 5 + Configuration Status Response 6 + Configuration Update Request 7 + Configuration Update Response 8 + WTP Event Request 9 + WTP Event Response 10 + Change State Event Request 11 + Change State Event Response 12 +*/ +#define CWMSG_ECHO_REQUEST 13 +#define CWMSG_ECHO_RESPONSE 14 +/* Image Data Request 15 + Image Data Response 16 +*/ + +#define CWMSG_RESET_REQUEST 17 +#define CWMSG_RESET_RESPONSE 18 + +/* + Reset Request 17 + Reset Response 18 +*/ +#define CWMSG_PRIMARY_DISCOVERY_REQUEST 19 +#define CWMSG_PRIMARY_DISCOVERY_RESPONSE 20 + +/* Data Transfer Request 21 + Data Transfer Response 22 + Clear Configuration Request 23 + Clear Configuration Response 24 + Station Configuration Request 25 + Station Configuration Response 26 +*/ + +#define CWMSG_MAXMSG 26 + + +/* +* CAPWAP message elements as defined in RFC 5416 +*/ + + +#define CWMSGELEM_AC_DESCRIPTOR 1 +/* AC IPv4 List 2 + AC IPv6 List 3 +*/ +#define CWMSGELEM_AC_NAME 4 +/* + AC Name with Priority 5 + AC Timestamp 6 + Add MAC ACL Entry 7 + Add Station 8 + Reserved 9 +*/ +#define CWMSGELEM_CONTROL_IPV4_ADDRESS 10 +#define CWMSGELEM_CONTROL_IPV6_ADDRESS 11 + +#define CWMSGELEM_CAPWAP_LOCAL_IPV4_ADDRESS 30 +#define CWMSGELEM_CAPWAP_LOCAL_IPV6_ADDRESS 50 +/* CAPWAP Timers 12 + CAPWAP Transport Protocol 51 + Data Transfer Data 13 + Data Transfer Mode 14 + Decryption Error Report 15 + Decryption Error Report Period 16 + Delete MAC ACL Entry 17 + Delete Station 18 + Reserved 19 +*/ +#define CWMSGELEM_DISCOVERY_TYPE 20 +/* + Duplicate IPv4 Address 21 + Duplicate IPv6 Address 22 +*/ +#define CWMSGELEM_ECN_SUPPORT 53 + /* Idle Timeout 23 + Image Data 24 + Image Identifier 25 + Image Information 26 + Initiate Download 27 + */ +#define CWMSGELEM_LOCATION_DATA 28 + +#define CWMSGELEM_MAXIMUM_MESSAGE_LENGTH 29 +#define CWMSGELEM_MTU_DISCOVERY_PADDING 52 + +/* Radio Administrative State 31 + Radio Operational State 32 +*/ +#define CWMSGELEM_RESULT_CODE 33 + +/* Returned Message Element 34 +*/ +#define CWMSGELEM_SESSION_ID 35 +/* Statistics Timer 36 + Vendor Specific Payload 37 + */ +#define CWMSGELEM_WTP_BOARD_DATA 38 + +#define CWMSGELEM_WTP_DESCRIPTOR 39 +/* WTP Fallback 40 + */ +#define CWMSGELEM_WTP_FRAME_TUNNEL_MODE 41 +/* + Reserved 42 + + + +*/ +/* + Reserved 43 +*/ +#define CWMSGELEM_WTP_MAC_TYPE 44 +#define CWMSGELEM_WTP_NAME 45 +/* + Unused/Reserved 46 + WTP Radio Statistics 47 + WTP Reboot Statistics 48 + WTP Static IP Address Information 49 +*/ + + + +/* wtp board data subelements */ +#define CWBOARDDATA_MODELNO 0 +#define CWBOARDDATA_SERIALNO 1 +#define CWBOARDDATA_BOARDID 2 +#define CWBOARDDATA_REVISION 3 +#define CWBOARDDATA_MACADDRESS 4 + + +/* */ +#define CWACSECURITY_FLAGS_R 1 /* Reserved */ +#define CWACSECURITY_FLAGS_S 2 /* DTLS psk */ +#define CWACSECURITY_FLAGS_X 4 /* X.509 */ + + +#define CWMSGSUBELEM_WTP_DESCRIPTOR_HARDWARE_VERSION 0 +#define CWMSGSUBELEM_WTP_DESCRIPTOR_SOFTWARE_VERSION 1 +#define CWMSGSUBELEM_WTP_DESCRIPTOR_BOOTLOADER_VERSION 2 +#define CWMSGSUBELEM_WTP_DESCRIPTOR_OTHERSOFTWARE_VERSION 3 + +#include "wtpinfo.h" +#include "acinfo.h" + +/* Frame tunnnel mode bits */ +#define WTP_FRAME_TUNNEL_MODE_R 1 /* Reserved */ +#define WTP_FRAME_TUNNEL_MODE_L 2 /* Local bridging */ +#define WTP_FRAME_TUNNEL_MODE_E 4 /* 802.3 mode */ +#define WTP_FRAME_TUNNEL_MODE_N 8 /* native mode */ + +#include "radioinfo.h" + +#include "wtpinfo.h" + + +#define CW_DISCOVERY_TYPE_UNKNOWN 0 +#define CW_DISCOVERY_TYPE_STATIC 1 +#define CW_DISCOVERY_TYPE_DHCP 2 +#define CW_DISCOVERY_TYPE_DNS 3 +#define CW_DISCOVERY_TYPE_AC_REFERRAL 4 + + + +/* wtpinfo methods */ +extern void wtpinfo_set_location(struct wtpinfo * wtpinfo, uint8_t * str, int len); +extern int wtpinfo_set_radioinfo(struct wtpinfo * wtpinfo,uint8_t *msgelem, int len); + + +#define CWRADIO_TYPE_B 1 +#define CWRADIO_TYPE_A 2 +#define CWRADIO_TYPE_G 4 +#define CWRADIO_TYPE_N 8 + +/* wtp mac types */ +#define WTP_MAC_TYPE_LOCAL 0 +#define WTP_MAC_TYPE_SPLIT 1 +#define WTP_MAC_TYPE_BOTH 2 + + + + +//#define CWMSG_MAX_SIZE 65536 +#define CWMSG_MAX_SIZE 2048 + +/* capwap timer default values */ +#define CAPWAP_DISCOVERY_INTERVAL 5 +#define CAPWAP_MAX_DISCOVERY_INTERVAL 20 +#define CAPWAP_RETRANSMIT_INTERVAL 3 +#define CAPWAP_MAX_DISCOVERIES 10 +#define CAPWAP_MAX_RETRANSMIT 5 +#define CAPWAP_SILENT_INTERVAL 30 +#define CAPWAP_ECHO_INTERVAL 30 + +#define CAPWAP_CIPHER "PSK-AES128-CBC-SHA" + + +/* AC descriptor security flags */ +#define AC_SECURITY_X 2 /* X.509 */ +#define AC_SECURITY_S 4 /* PSK support */ + +/* AC dtls policy flags */ +#define AC_DTLS_POLICY_C 2 /* Clear data channel support */ +#define AC_DTLS_POLICY_D 4 /* DTLS Data channel support */ + + +//struct capwap_msg * capwap_msg_new(); +//int cwmsg_send(struct cwmsg * cwmsg, ); +// void cwmsg_send(struct cwmsg * cwmsg ,struct conn * conn); //connint8_t * buffer,int msglen) +//void cwmsg_send(struct cwmsg * cwmsg, int rid, uint32_t * rmac, struct conn * conn) ; +//void cwmsg_send(struct cwmsg * cwmsg, int seqnum, int rid, struct conn * conn); + +//extern void cwmsg_init(struct cwmsg * msg, uint8_t *buffer,int flag); +//extern void cwmsg_init(struct cwmsg * cwmsg, uint8_t *buffer, int type, uint8_t * rmac); +//void cwmsg_init(struct cwmsg * cwmsg, uint8_t *buffer, int type, struct radioinfo * radioinfo); + +extern void cwmsg_addelem_wtp_descriptor(struct cwmsg * cwmsg, struct wtpinfo * wtpinfo); +extern void cwmsg_addelem_ctrl_ip_addrs(struct cwmsg *msg, struct ac_info *acinfo); +extern void cwmsg_addelem_wtp_board_data(struct cwmsg * cwmsg, struct wtpinfo * wtpinfo); +extern void cwmsg_addelem_cw_local_ip_addr(struct cwmsg *msg, struct conn * conn); +extern void cwmsg_addelem_wtp_radio_infos(struct cwmsg * cwmsg,struct wtpinfo * wtpinfo); +extern void cwmsg_addelem_result_code(struct cwmsg *msg,int rc); + +//extern void cwsend_discovery_reponse(struct conn * conn, struct ac_info * acinfo); +//extern int process_msgelems(uint8_t * msgelems, int len, +// int (*callback)(void*,int,uint8_t*,int),void *arg ); + + + + +//void cwsend_discovery_response(struct conn * conn,int seqnum, struct radioinfo * radioinfo, struct ac_info * acinfo, struct wtpinfo * wtpinfo); +// +extern void cwsend_discovery_response(struct conn * conn,int seqnum, struct radioinfo * radioinfo, struct ac_info * acinfo, struct wtpinfo * wtpinfo); +extern int cwsend_discovery_request(struct conn * conn,struct radioinfo * radioinfo,struct wtpinfo * wtpinfo); +extern void cwsend_join_response(struct conn * conn,int seqnum, int rc, struct radioinfo * radioinfo, struct ac_info * acinfo, struct wtpinfo * wtpinfo); + + +extern void process_discovery_request(struct wtpinfo * wtpinfo, uint8_t * msg, int len); +extern void process_join_request(struct wtpinfo * wtpinfo, uint8_t * msg, int len); +void cwread_discovery_response(struct ac_info * acinfo, uint8_t * msg, int len); + + +#endif diff --git a/src/capwap/capwap_ieee80211.h b/src/capwap/capwap_ieee80211.h new file mode 100644 index 00000000..3be68672 --- /dev/null +++ b/src/capwap/capwap_ieee80211.h @@ -0,0 +1,29 @@ + +#define CWMSGELEM_IEEE80211_ADD_WLAN 1024 +/* IEEE 802.11 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 + IEEE 802.11 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 +*/ + +#define CWMSGELEM_IEEE80211_WTP_RADIO_INFO 1048 + diff --git a/src/capwap/capwap_msg_new.c b/src/capwap/capwap_msg_new.c new file mode 100644 index 00000000..ab8ffe57 --- /dev/null +++ b/src/capwap/capwap_msg_new.c @@ -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 . + +*/ + +#include "capwap.h" + +struct capwap_msg * capwap_msg_new() +{ + + +} diff --git a/src/capwap/capwap_parse_ctrlhdr.c b/src/capwap/capwap_parse_ctrlhdr.c new file mode 100644 index 00000000..788f5c97 --- /dev/null +++ b/src/capwap/capwap_parse_ctrlhdr.c @@ -0,0 +1,41 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include "capwap.h" + +int capwap_parse_ctrlhdr(struct capwap_ctrlhdr * ch,uint8_t * msg, int len) +{ + if (len<8) + return 0; + + uint32_t val; + ch->msgtype = ntohl(*((uint32_t*)(msg)))-CWIANA_ENTERPRISE_NUMBER*256; + val = ntohl(*((uint32_t*)(msg+4))); + ch->seqnum = CW_GET_DWORD_BITS(val,0,8); + ch->msgelemslen=CW_GET_DWORD_BITS(val,8,16)-3; + ch->flags=CW_GET_DWORD_BITS(val,24,8); + ch->msgelems=msg+8; + + if (8+ch->msgelemslen != len) + { + return 0; + } + return 1; +} + + diff --git a/src/capwap/conn.c b/src/capwap/conn.c new file mode 100644 index 00000000..b43644e0 --- /dev/null +++ b/src/capwap/conn.c @@ -0,0 +1,117 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include +#include +#include + +#include "conn.h" +#include "capwap.h" +#include "sock.h" + +#include "cw_log.h" + +/** + * function + * @retval 1 Success + * @retval 0 failure, conslt errno for more details + */ +struct conn * conn_create(int sock, struct sockaddr * addr, +// void (*process_message)(void *arg,uint8_t *hdr,uint8_t *msg, int len), +// void (*process_message)(void *arg,struct cwrmsg *), //uint8_t *hdr,uint8_t *msg, int len), +// void *pmsgarg, + int qsize) + +{ + struct conn * conn; + conn = malloc(sizeof (struct conn)); + if (!conn) + return NULL; + + memset(conn,0,sizeof(struct conn)); + + conn->sock=sock; + + if (addr) + sock_copyaddr(&conn->addr,addr); + +// printf("AF IN: %i\n",addr->sa_family); + char str[200] ; + sock_addrtostr((struct sockaddr*)&conn->addr,str,200); +// printf("CONN CREATOR: %s\n",str); + + 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,"sem_init %s",strerror(errno)); + conn_destroy(conn); + return NULL; + }; + conn->recv_packet=conn_q_recv_packet; + } + else + conn->recv_packet = conn_recv_packet; + + +// conn->process_message=process_message; +// conn->pmsgarg=pmsgarg; + + conn->last_seqnum_received=-1; + conn->mtu=1500; + + conn->send_packet = conn_send_packet; + + conn->cur_packet=0; + conn->recv_timeout=1; + + conn->seqnum=-1; + conn->write = conn->send_packet; + conn->read = conn->recv_packet; + + + return conn; +} + + +void conn_destroy(struct conn * conn) +{ + if (conn->fragman) + fragman_destroy(conn->fragman); + if (conn->q) + free (conn->q); + + free(conn); +} + +/* +void connn_get_next_seqnum(struct conn * conn) +{ + return (++conn->seqnum)&0xff; +} +*/ diff --git a/src/capwap/conn.h b/src/capwap/conn.h new file mode 100644 index 00000000..96a4e868 --- /dev/null +++ b/src/capwap/conn.h @@ -0,0 +1,147 @@ +/* + 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 . + +*/ + + +#ifndef __CONN_H +#define __CONN_H + +#include +#include +#include +#include + +#include "fragman.h" +#include "cwmsg.h" +#include "cwrmsg.h" + + +struct conn{ + int sock; + struct sockaddr_storage addr; + int recv_timeout; + + FRAGMAN * fragman; +// void (* process_message)(void *,uint8_t *,uint8_t *, int); + +// void (* process_message)(void *,struct cwrmsg *); //uint8_t *,uint8_t *, int); +// void * pmsgarg; + + int fragid; + + int seqnum; + + int last_seqnum_received; + int last_message_id_received; + + struct cwmsg * last_response; + struct cwmsg swm; + int last_response_seqnum; + int last_response_rid; + + uint8_t buffer[65536]; + int mtu; + + /* receive and send methods */ + + int (*recv_packet)(struct conn *, uint8_t *,int); + int (*send_packet)(struct conn *, const uint8_t *, int); + + int (*read)(struct conn *, uint8_t*, int); + int (*write)(struct conn *, const uint8_t*, int); + + /* optional packet queue */ + uint8_t ** q; //[WTPMAN_QSIZE]; + int qsize; + int qrpos; + int qwpos; + sem_t q_sem; + uint8_t * cur_packet; + int cur_packet_len; + int cur_packet_pos; + +#ifdef WITH_DTLS + /* 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; + void * dtls_data; + char * dtls_cipher; +#endif + /* used to link the conn obj with other objects */ + void * data; +}; + + + +struct conn * conn_create(int sock, struct sockaddr * addr, +// void (*process_message)(void *arg,uint8_t *hdr,uint8_t *msg, int len), +// void (*process_message)(void *arg,struct cwrmsg *), //uint8_t *hdr,uint8_t *msg, int len), +// void *pmsgarg, + int qsize); + + +extern int conn_send_cwmsg(struct conn * conn, struct cwmsg * cwmsg); +extern void conn_process_packet(struct conn * conn, uint8_t *packet, int len,int(*cb)(void*,struct cwrmsg*),void *cbarg); +extern struct cwrmsg * 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_recv_packet(struct conn* conn,uint8_t *buf,int len); + +#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); + + + + + + + + +#endif /* __CONLIST_H */ + diff --git a/src/capwap/conn_get_message.c b/src/capwap/conn_get_message.c new file mode 100644 index 00000000..84d888a8 --- /dev/null +++ b/src/capwap/conn_get_message.c @@ -0,0 +1,51 @@ + + +#include +#include +#include + +#include "conn.h" +#include "cwrmsg.h" + + + + +static int pmessage(void *w, struct cwrmsg * cwrmsg) +{ + uint8_t * buffer; + buffer = malloc( sizeof (struct cwrmsg) + cwrmsg->msgelems_len); + memcpy(buffer,cwrmsg,sizeof(struct cwrmsg)); + memcpy(buffer+sizeof(struct cwrmsg),cwrmsg->msgelems,cwrmsg->msgelems_len); + ((struct cwrmsg*)(buffer))->msgelems=buffer+sizeof(struct cwrmsg); + *((void**)w) = (void*)buffer; + return 0; +} + + + + +struct cwrmsg * conn_get_message(struct conn * conn) +{ + struct cwrmsg * cwrmsg=0; +// conn->process_message=pmessage; +// conn->pmsgarg=&cwrmsg; + + uint8_t buf[2048]; + int len=2048; +// int flags=0; + + + int n; +// do { +// n = conn->recv_packet(conn,(char*)buf,len); + n = conn->read(conn,buf,len); +// +// printf("GETMPACK %i\n",n); + if (n>0) + conn_process_packet(conn,buf,n,pmessage,&cwrmsg); + +// } while (cwrmsg==0); + + return cwrmsg; +} + diff --git a/src/capwap/conn_process_packet.c b/src/capwap/conn_process_packet.c new file mode 100644 index 00000000..54393437 --- /dev/null +++ b/src/capwap/conn_process_packet.c @@ -0,0 +1,152 @@ +#include + +#include "capwap.h" +#include "cw_log.h" +#include "conn.h" + + +static int cwrmsg_init_ctrlhdr(struct cwrmsg * cwrmsg, uint8_t * msg, int len) +{ + if (len<8) + return 0; + + uint32_t val; + val = ntohl(*((uint32_t*)(msg+0))); + + cwrmsg->type = ntohl(*((uint32_t*)(msg)))-CWIANA_ENTERPRISE_NUMBER*256; + + val = ntohl(*((uint32_t*)(msg+4))); + cwrmsg->seqnum = CW_GET_DWORD_BITS(val,0,8); + cwrmsg->msgelems_len=CW_GET_DWORD_BITS(val,8,16)-3; +// ch->flags=CW_GET_DWORD_BITS(val,24,8); + cwrmsg->msgelems=msg+8; + + if (8+cwrmsg->msgelems_len != len){ + return 0; + } + + return 1; + +} + + +static int process_message(struct conn * conn,struct cwrmsg *cwrmsg,int (*cb)(void*,struct cwrmsg *),void *cbarg) +{ + if (!(cwrmsg->type & 0x1)) { + /* It's a response message, no further examination required. */ +// conn->process_message(conn->pmsgarg,cwrmsg); + cb(cbarg,cwrmsg); + + return 0; + } + + /* It's a request message, check if seqnum is right and if + * we have already sent a response message*/ + + int s1=conn->last_seqnum_received; + int s2=cwrmsg->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=cwrmsg->seqnum; + cb(cbarg,cwrmsg); + return 0; + } + + if (sd != 0) + { + cw_log_debug0("Discarding message, old seqnum, seqnum = %d, last seqnum=%d",s2,s1); + return 1; + } + + /* the received request message was retransmitte by our peer, + * let's retransmit our response message if we have one*/ + + cw_log_debug0("Retransmitted request message detected, seqnum=%d",s2); + + if (!conn->last_response){ + cw_log_debug0("No cached response for retransmission, request seqnum=%d",s2); + return 0; + } + + cw_log_debug0("Retransmitting response message, seqnum=%d",s2); +// cwmsg_send(conn->last_response,conn->last_response_seqnum,conn->last_response_rid,conn); + conn_send_cwmsg(conn,conn->last_response); + return 1; +} + + + +void conn_process_packet(struct conn * conn, uint8_t *packet, int len,int (*cb)(void*,struct cwrmsg*),void *cbarg) +{ + + cw_log_debug2("Process conn Packet received, len=%d",len); + + if (len<8){ + /* packet too short */ + cw_log_debug0("Discarding packet, packet too short, len=%d",len); + return; + } + + uint32_t val = ntohl(*((uint32_t*)packet)); + + int preamble = val >> 24; + if ( (preamble & 0xf0) != CW_VERSION){ + /* wrong version */ + cw_log_debug0("Discarding packet, wrong version, version=%d",preamble&0xf0); + return; + } + + if (preamble & 0xf ) { + /* decode dtls */ + return; + } + + int hlen = 4*((val >> 19) & 0x1f); + + int payloadlen = len - hlen; + if (payloadlen<0){ + cw_log_debug0("Discarding packet, hlen greater than len, hlen=%d",hlen); + /* EINVAL */ + return; + } + + + struct cwrmsg cwrmsg; + cwrmsg.wbid=(val>>9) & 0x1f; + cwrmsg.rid=(val>>14) & 0x1f; + +#ifdef WITH_RMAC_SUPPORT + if (val & CWTH_FLAGS_M){ + if (*(packet+8)+8>hlen){ + cw_log_debug0("Discarding packet, wrong rmac size, size=%d",*(packet+8)); + /* wrong rmac size */ + return; + } + cwrmsg.rmac = packet+8; + } + else + cwrmsg.rmac=NULL; +#endif + + + if (val & CWTH_FLAGS_F){ /* fragmented */ + uint8_t * f; +// printf("fragman add\n"); + f = fragman_add(conn->fragman, packet,hlen,payloadlen); + if (f==NULL) + return; +// printf("complete\n"); +// printf ("msglen = %i\n",*((uint32_t*)f)); + cwrmsg_init_ctrlhdr(&cwrmsg,f+4,*(uint32_t*)f); + process_message(conn,&cwrmsg,cb,cbarg); //packet,f+4,*(int32_t*)f); + free (f); + return; + } + + cwrmsg_init_ctrlhdr(&cwrmsg,packet+hlen,len-hlen); //f+4,*(uint32_t*)f); + process_message(conn,&cwrmsg,cb,cbarg); //packet,f+4,*(int32_t*)f); + return; +} + diff --git a/src/capwap/conn_q_add_packet.c b/src/capwap/conn_q_add_packet.c new file mode 100644 index 00000000..361d280f --- /dev/null +++ b/src/capwap/conn_q_add_packet.c @@ -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 . + +*/ + +#include +#include + +#include "cw_log.h" +#include "conn.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_log_debug0( "Discarding packet, no queu buffers left"); + 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); +} + + + diff --git a/src/capwap/conn_q_get_packet.c b/src/capwap/conn_q_get_packet.c new file mode 100644 index 00000000..63a4203c --- /dev/null +++ b/src/capwap/conn_q_get_packet.c @@ -0,0 +1,32 @@ + +#include + +#include "conn.h" + + +uint8_t * conn_q_get_packet(struct conn * conn) +{ + struct timespec timespec; + clock_gettime(CLOCK_REALTIME,×pec); + timespec.tv_sec++; + + +// sem_wait(&conn->q_sem); + 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]; +/* + uint8_t * packet = conn->q[qrpos]+4; + int len = *( (uint32_t*)(conn->q[qrpos])); + + conn_process_packet(conn->conn,packet,len); +// free(conn->q[qrpos]); +*/ + +} + diff --git a/src/capwap/conn_q_recv_packet.c b/src/capwap/conn_q_recv_packet.c new file mode 100644 index 00000000..e1b517a9 --- /dev/null +++ b/src/capwap/conn_q_recv_packet.c @@ -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 . + +*/ + +#include +#include +#include + +#include "conn.h" + +int conn_q_recv_packet(struct conn * conn, uint8_t * buffer,int len) +{ + 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); + conn->cur_packet_pos+=len; + conn->cur_packet_len-=len; + return len; + + } + + memcpy(buffer,conn->cur_packet+conn->cur_packet_pos,conn->cur_packet_len); + free (conn->cur_packet); + conn->cur_packet=0; + return conn->cur_packet_len; +} diff --git a/src/capwap/conn_recv_packet.c b/src/capwap/conn_recv_packet.c new file mode 100644 index 00000000..ce6f701c --- /dev/null +++ b/src/capwap/conn_recv_packet.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include + +#include "conn.h" + + +int conn_recv_packet(struct conn* conn,uint8_t *buf,int len) +{ +// printf("Conn recv packet called\n"); + int n; + int flags=0; + while( (n = recv(conn->sock,(char*)buf,len,flags)) < 0 ){ + if (errno!=EINTR) + { +/* if (errno == EWOULDBLOCK) + { + printf("would block\n"); + } + if ( errno==EAGAIN ) + { + printf("again\n"); + } + perror("recv"); +*/ + return n; + } + } + return n; +} + + diff --git a/src/capwap/conn_send_cwmsg.c b/src/capwap/conn_send_cwmsg.c new file mode 100644 index 00000000..8f2c40c1 --- /dev/null +++ b/src/capwap/conn_send_cwmsg.c @@ -0,0 +1,96 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ +#include + +#include "conn.h" +#include "capwap.h" + +int conn_send_cwmsg(struct conn * conn, struct cwmsg * cwmsg) +{ + uint32_t val; + + /* second dword of message control header */ + val = (cwmsg->seqnum<<24)|((cwmsg->pos+3)<<8); + *((uint32_t*)(cwmsg->ctrlhdr+4))=htonl(val); + + +// int msglen = cwmsg->ctrlhdr-cwmsg->buffer+cwmsg->pos; + int msglen = cwmsg->pos+8; + + uint8_t * ptr = cwmsg->buffer; + int fragoffset = 0; + int hlen = cwmsg->hlen*4; + +// printf("Hlen is %i\n",hlen); + + + int preamble = CW_VERSION | 0; + + + int wbid=CWTH_WBID_IEEE80211; + int packetlen = msglen+hlen; + int mtu = conn->mtu; + + while (packetlen>mtu){ + val = (preamble << 24) | ((hlen/4)<<19) | (cwmsg->rid<<14) |(wbid<<9) | + CWTH_FLAGS_T | + CWTH_FLAGS_F | + cwmsg->flags; + *((uint32_t*)ptr)=htonl(val); + +// printf("setting frag id : %i\n",conn->fragid); + val = conn->fragid<<16 | fragoffset<<3; +// printf("VAAL: %08X\n",val); + *((uint32_t*)(ptr+4))=htonl(val); + +// printf("Offset = %d\n",fragoffset); + +// if (conn_send_packet(conn,ptr,mtu)<0) +// return -1; + if (conn->write(conn,ptr,mtu)<0) + return -1; + + ptr +=mtu-hlen; + fragoffset+=(mtu-hlen)/8; + + packetlen-=mtu-hlen; +// printf("Packelen=%d\n",packetlen); + + 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; + + if (fragoffset){ + val |= CWTH_FLAGS_F | CWTH_FLAGS_L; + } + + +// printf("Setting first byte %08X\n",val); + *((uint32_t*)ptr)=htonl(val); + + + val = conn->fragid<<16 | fragoffset<<3; + *((uint32_t*)(ptr+4))=htonl(val); + + return conn->write(conn,ptr,msglen-fragoffset*8+hlen); +} + diff --git a/src/capwap/conn_send_packet.c b/src/capwap/conn_send_packet.c new file mode 100644 index 00000000..3ea9570e --- /dev/null +++ b/src/capwap/conn_send_packet.c @@ -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 . + +*/ + +#include +#include +#include "sock.h" +#include "conn.h" + +#include +#include + + +#include "cw_log.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; +} diff --git a/src/capwap/connlist.c b/src/capwap/connlist.c new file mode 100644 index 00000000..734db01e --- /dev/null +++ b/src/capwap/connlist.c @@ -0,0 +1,98 @@ + +#include +#include +#include + +#include +#include +#include + + + +#include + +#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->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); +} + + + diff --git a/src/capwap/cw_foreach_msgelem.c b/src/capwap/cw_foreach_msgelem.c new file mode 100644 index 00000000..7aeadf87 --- /dev/null +++ b/src/capwap/cw_foreach_msgelem.c @@ -0,0 +1,46 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include "capwap.h" + +/* + * for each capwap message element in msgelems call the callback function + */ +int cw_foreach_msgelem(uint8_t * msgelems, int len, + int (*callback)(void*,int,uint8_t*,int),void *arg ) +{ + uint32_t val; + int type; + int elen; + int i=0; + do { + val = ntohl(*(uint32_t*)(msgelems+i)); + type=(val>>16) & 0xFFFF; + elen = val & 0xffff; + if (i+elen+4>len) { + return 0; + } + + callback(arg,type,msgelems+i+4,elen); + i+=elen+4; + + } while (i. + +*/ + + +#include + +#include "cw_log.h" + +void (*cw_log_cb)(int level,const char * fromat, ...) = CW_LOG_DEFAULT_LOG; +const char * cw_log_name = "cw"; + diff --git a/src/capwap/cw_log.h b/src/capwap/cw_log.h new file mode 100644 index 00000000..1db50b1c --- /dev/null +++ b/src/capwap/cw_log.h @@ -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 . + +*/ +#ifndef __CW_LOG_H +#define __CW_LOG_H + +#include +#include +#include + +#ifndef CW_LOG_DUMP_ROW_LEN + #define CW_LOG_DUMP_ROW_LEN 32 +#endif + +#ifndef CW_LOG_DUMP_ROW_TAB_LEN + #define CW_LOG_DUMP_ROW_TAB_LEN 8 +#endif + +#ifndef CW_LOG_DEFAULT_LOG + #define CW_LOG_DEFAULT_LOG cw_log_tosyslog +#endif + + + +#ifdef WITH_CW_LOG + #define cw_log(level,...) cw_log_cb(level,__VA_ARGS__) +#else + #define cw_log(...) +#endif + +#ifdef WITH_CW_LOG_DEBUG + #define cw_log_debug0(...) cw_log_debug_cbs[0](__VA_ARGS__) + #define cw_log_debug1(...) cw_log_debug_cbs[1](__VA_ARGS__) + #define cw_log_debug2(...) cw_log_debug_cbs[2](__VA_ARGS__) + #define cw_log_debug_dump(level,str,len,...) cw_log_debug_dump_(level,str,len,__VA_ARGS__) + #define cw_log_debug0_dump(str,len,...) cw_log_debug_dump_(0,str,len,__VA_ARGS__) + #define cw_log_debug1_dump(str,len,...) cw_log_debug_dump_(1,str,len,__VA_ARGS__) + #define cw_log_debug2_dump(str,len,...) cw_log_debug_dump_(2,str,len,__VA_ARGS__) + #define cw_log_debug(level,...) cw_log_debug_cbs[level](__VA_ARGS__) + +#else + #define cw_log_debug0(...) + #define cw_log_debug1(...) + #define cw_log_debug2(...) + #define cw_log_debug(...) + #define cw_log_debug_dump(level,str,len) + #define cw_log_debug0_dump(level,str,len) + #define cw_log_debug1_dump(level,str,len) + #define cw_log_debug2_dump(level,str,len) +#endif + +extern void (*cw_log_cb)(int level,const char * fromat, ...); +extern void (*cw_log_debug_cbs[])(const char * fromat, ...); +extern int cw_log_debug_dump_(int level,const uint8_t * data, int len, const char * format, ...); +extern void cw_vlog_(int level,const char * format, va_list args); +extern int cw_log_debug_level; +extern void cw_log_tosyslog(int level,const char *format, ...); +extern void cw_log_tofile(int level,const char *format, ...); + +extern const char * cw_log_name; + +#endif diff --git a/src/capwap/cw_log_debug.c b/src/capwap/cw_log_debug.c new file mode 100644 index 00000000..cfb73dab --- /dev/null +++ b/src/capwap/cw_log_debug.c @@ -0,0 +1,116 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include +#include +#include + +#include "cw_log.h" + + + +static void cw_log_debug0_(const char *format, ...) +{ + if (cw_log_debug_level<0) + return; + va_list args; + va_start(args, format); + cw_vlog_(LOG_DEBUG,format,args); + va_end(args); + closelog(); +} + +static void cw_log_debug1_(const char *format, ...) +{ + if (cw_log_debug_level<1) + return; + + va_list args; + va_start(args, format); + cw_vlog_(LOG_DEBUG,format,args); + va_end(args); + closelog(); +} + +static void cw_log_debug2_(const char *format, ...) +{ + if (cw_log_debug_level<2) + return; + va_list args; + va_start(args, format); + cw_vlog_(LOG_DEBUG,format,args); + va_end(args); + closelog(); +} + +int cw_log_debug_dump_(int level,const uint8_t * data, int len,const char * format, ...) +{ + int maxtlen=2048; + int i; + int rowlen = CW_LOG_DUMP_ROW_LEN; + int rows = len/rowlen; + int tlen=0; + + char * dst = malloc(len*3+(rows*2) + 8+maxtlen); + if ( !dst ) + return 0; + + if (format != NULL){ + va_list args; + va_start(args,format); + tlen = vsnprintf(dst,maxtlen,format,args); + va_end(args); + } + + + + if (len%CW_LOG_DUMP_ROW_LEN) + rows++; + + + + char * pdst=dst+tlen; + sprintf(pdst,"\n\t"); + pdst+=2; + + for (i=0; i + +#include "cw_log.h" + + +int cw_log_file_flags = LOG_PERROR; +char * cw_log_filename = NULL; + + +void cw_vlog_tofile_(int level,const char * format, va_list args) +{ + switch(level){ + case LOG_DEBUG: + printf("DEBUG:"); + break; + case LOG_INFO: + printf("INFO:"); + break; + } + vprintf(format,args); + +} + +void cw_log_tofile(int level,const char *format, ...) +{ + va_list args; + va_start(args, format); + +// cw_vlog_(level,format,args); + cw_vlog_tofile_(level,format,args); + va_end(args); + closelog(); +} + + diff --git a/src/capwap/cw_log_tosyslog.c b/src/capwap/cw_log_tosyslog.c new file mode 100644 index 00000000..91d9ff45 --- /dev/null +++ b/src/capwap/cw_log_tosyslog.c @@ -0,0 +1,20 @@ + +#include "cw_log.h" + + +void cw_vlog_(int level,const char * format, va_list args) +{ + openlog (cw_log_name, LOG_PERROR | LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DEBUG); + vsyslog(level,format,args); +} + +void cw_log_tosyslog(int level,const char *format, ...) +{ + va_list args; + va_start(args, format); + cw_vlog_(level,format,args); + va_end(args); + closelog(); +} + + diff --git a/src/capwap/cw_msgelemtostr.c b/src/capwap/cw_msgelemtostr.c new file mode 100644 index 00000000..7810ceaa --- /dev/null +++ b/src/capwap/cw_msgelemtostr.c @@ -0,0 +1,12 @@ + + +:q + + + + + +const cw_msgelemtostr(int elem) +{ + +} diff --git a/src/capwap/cw_pseudo_rand.c b/src/capwap/cw_pseudo_rand.c new file mode 100644 index 00000000..a7ecf44d --- /dev/null +++ b/src/capwap/cw_pseudo_rand.c @@ -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 . + +*/ + +#include +#include +#include + +int cw_pseudo_rand(uint8_t *dst, int len) +{ + static int init = 1; + if (init){ + srand(time(NULL)); + } + int i; + for (i=0; i. + +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "cw_util.h" +#include "cw_log.h" + +char * cw_rand_dev = "/dev/random"; + +int cw_rand(uint8_t*dst, int len) +{ + int rf; + int l; + + rf = open(cw_rand_dev, O_RDONLY | O_NDELAY); + if (rf<0){ + + cw_log(LOG_ERR,"Can't open %s: %s",cw_rand_dev,strerror(errno)); + return cw_pseudo_rand(dst,len); + } + + + l = read(rf, dst, len); + close(rf); + + if ((l<0) && (errno != EAGAIN)){ + cw_log(LOG_ERR,"Cant read from %s: %s",cw_rand_dev,strerror(errno)); + return cw_pseudo_rand(dst,len); + } + + if (l. + +*/ + +#include +#include + +#include "cw_util.h" + +uint8_t * cw_setstr(uint8_t ** dst, const uint8_t *src, int len) +{ + *dst = realloc(*dst,len+1); + if (*dst==NULL) + return NULL; + memcpy(*dst,src,len); + (*dst)[len]=0; + return *dst; +} + + diff --git a/src/capwap/cw_util.h b/src/capwap/cw_util.h new file mode 100644 index 00000000..8024fadc --- /dev/null +++ b/src/capwap/cw_util.h @@ -0,0 +1,31 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include + +extern uint8_t * cw_setstr(uint8_t ** dst, const uint8_t *src, int len); + + +extern int cw_foreach_msgelem(uint8_t * msgelems, int len, + int (*callback)(void*,int,uint8_t*,int),void *arg ); + + +extern int cw_pseudo_rand(uint8_t *dst, int len); +extern int cw_rand(uint8_t*dst, int len); + + diff --git a/src/capwap/cwmsg.h b/src/capwap/cwmsg.h new file mode 100644 index 00000000..60e92f60 --- /dev/null +++ b/src/capwap/cwmsg.h @@ -0,0 +1,34 @@ +#ifndef __CWMSG_H +#define __CWMSG_H + +#include + +#include "radioinfo.h" +#include "acinfo.h" + +struct cwmsg{ + uint8_t * buffer; + uint8_t * trnsprthdr; + uint8_t * ctrlhdr; + uint8_t * msgelems; + int pos; + int flags; + int hlen; + int rid; + int seqnum; + int type; +}; + +struct conn; + +extern void cwmsg_init(struct cwmsg * cwmsg, uint8_t *buffer, int type, int seqnum, struct radioinfo * radioinfo); +//int cwmsg_send(struct cwmsg * cwmsg, int seqnum, int rid, struct conn * conn); +// +extern void cwmsg_addelem(struct cwmsg *msg,int type, const uint8_t *elem, int len); +extern void cwmsg_addelem_ac_descriptor(struct cwmsg *msg,struct ac_info * acinfo); + + +extern void cwmsg_init_echo_request(struct cwmsg * cwmsg,uint8_t *buffer,struct conn * conn, struct radioinfo * radioinfo); + + +#endif diff --git a/src/capwap/cwmsg_addelem.c b/src/capwap/cwmsg_addelem.c new file mode 100644 index 00000000..56f1c0d9 --- /dev/null +++ b/src/capwap/cwmsg_addelem.c @@ -0,0 +1,32 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include +#include + +#include "cwmsg.h" + + +void cwmsg_addelem(struct cwmsg *msg,int type,const uint8_t*elem,int len) +{ + uint32_t val = type<<16|len; + *((uint32_t*)(msg->msgelems+msg->pos))=htonl(val); + memcpy(msg->msgelems+4+msg->pos,elem,len); + msg->pos+=4+len; +} + diff --git a/src/capwap/cwmsg_addelem_ac_descriptor.c b/src/capwap/cwmsg_addelem_ac_descriptor.c new file mode 100644 index 00000000..3d033cf4 --- /dev/null +++ b/src/capwap/cwmsg_addelem_ac_descriptor.c @@ -0,0 +1,57 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include +#include "capwap.h" + +void cwmsg_addelem_ac_descriptor(struct cwmsg *msg,struct ac_info * acinfo) +{ + uint8_t buffer[12+2048]; + uint8_t * acd = buffer; + + *((uint32_t*)(acd))=htonl((acinfo->stations<<16) | (acinfo->limit)); + *((uint32_t*)(acd+4))=htonl((acinfo->active_wtps<<16) | acinfo->max_wtps); + *((uint32_t*)(acd+8))=htonl((acinfo->security<<24) | (acinfo->rmac<<16) | acinfo->dtls_policy ); + + int len = 12; + int sublen; + + /* hardware version subelement */ + *((uint32_t*)(acd+len))=0; + len+=4; + sublen=strlen(acinfo->hardware_version); + *((uint32_t*)(acd+len))=htonl((4<<16)|sublen); + len+=4; + memcpy(acd+len,acinfo->hardware_version,sublen); + len+=sublen; + + /* software version subelement */ + *((uint32_t*)(acd+len))=0; + len+=4; + sublen=strlen(acinfo->software_version); + *((uint32_t*)(acd+len))=htonl((5<<16)|sublen); + len+=4; + memcpy(acd+len,acinfo->software_version,sublen); + len+=sublen; + + + cwmsg_addelem(msg,CWMSGELEM_AC_DESCRIPTOR,acd,len); + +} + + diff --git a/src/capwap/cwmsg_addelem_ctrl_ip_addrs.c b/src/capwap/cwmsg_addelem_ctrl_ip_addrs.c new file mode 100644 index 00000000..933ca8e0 --- /dev/null +++ b/src/capwap/cwmsg_addelem_ctrl_ip_addrs.c @@ -0,0 +1,103 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ +#include +#include + +#include "capwap.h" +#include "acinfo.h" + + +#include "sock.h" + +//static int cwmsg_addelem_acip(struct cwmsg * msg,ACIP *ip,int ctr) +static int cwmsg_addelem_acip(void * priv,void *data,int ctr) +{ + struct cwmsg * msg = (struct cwmsg*)priv; + ACIP * acip = (ACIP*)data; + + uint8_t ipmsg [18]; + + switch (acip->ip.ss_family){ + case AF_INET: + { + struct sockaddr_in * sain = (struct sockaddr_in*)&acip->ip; + memcpy(ipmsg,&sain->sin_addr.s_addr, sizeof(sain->sin_addr.s_addr)); + *((uint16_t*)(ipmsg+4))= htons(acip->wtp_count); /* number of wtps */ + cwmsg_addelem(msg,CWMSGELEM_CONTROL_IPV4_ADDRESS,ipmsg,6); + } + break; +#ifdef WITH_IPV6 + case AF_INET6: + { + struct sockaddr_in6 * sain = (struct sockaddr_in6*)&acip->ip; + memcpy(ipmsg,&sain->sin6_addr.s6_addr, sizeof(sain->sin6_addr.s6_addr)); + *((uint16_t*)(ipmsg+16))= htons(acip->wtp_count); /* number of wtps */ + cwmsg_addelem(msg,CWMSGELEM_CONTROL_IPV6_ADDRESS,ipmsg,18); + } + break; +#endif + } + return 1; +} + + +void cwmsg_addelem_ctrl_ip_addrs(struct cwmsg *msg, struct ac_info *acinfo) +{ +// printf("Counter in the list: %i\n",acinfo->aciplist->count); + aciplist_foreach(acinfo->aciplist,cwmsg_addelem_acip,msg); +} + + + + +void ucwmsg_addelem_ctrl_ip_addrs(struct cwmsg *msg, struct ac_info *acinfo) +{ + int i; + +// printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaaaa\n"); +// printf("add elem %i\n",acinfo->salist_len); + + for (i=0; isalist_len; i++) + { + uint8_t ipmsg [18]; + switch (acinfo->salist[i].sa_family){ + case AF_INET: + { +// printf("v4\n"); + struct sockaddr_in * sain = (struct sockaddr_in*)&acinfo->salist[i]; + memcpy(ipmsg,&sain->sin_addr, sizeof(sain->sin_addr)); + *((uint16_t*)(ipmsg+4))= htons(0); /* number of wtps */ + cwmsg_addelem(msg,CWMSGELEM_CONTROL_IPV4_ADDRESS,ipmsg,6); + } + break; +#ifdef WITH_IPV6 + case AF_INET6: + { +// printf("v6\n"); + struct sockaddr_in6 * sain = (struct sockaddr_in6*)&acinfo->salist[i]; + memcpy(ipmsg,&sain->sin6_addr, sizeof(sain->sin6_addr)); + *((uint16_t*)(ipmsg+16))= htons(0); /* number of wtps */ + cwmsg_addelem(msg,CWMSGELEM_CONTROL_IPV6_ADDRESS,ipmsg,18); + } + break; +#endif + } + } +} + + diff --git a/src/capwap/cwmsg_addelem_cw_local_ip_addr.c b/src/capwap/cwmsg_addelem_cw_local_ip_addr.c new file mode 100644 index 00000000..4db9b36b --- /dev/null +++ b/src/capwap/cwmsg_addelem_cw_local_ip_addr.c @@ -0,0 +1,55 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include +#include +#include + +#include + + +#include "capwap.h" +#include "cwmsg.h" +#include "conn.h" + + +void cwmsg_addelem_cw_local_ip_addr(struct cwmsg *msg, struct conn * conn) +{ + struct sockaddr_storage a; + socklen_t alen = sizeof(struct sockaddr_storage); + getsockname (conn->sock,(struct sockaddr *)&a,&alen); + + switch (((struct sockaddr*)&a)->sa_family){ + case AF_INET: + { + struct sockaddr_in * sain = (struct sockaddr_in*)&a; + cwmsg_addelem(msg,CWMSGELEM_CAPWAP_LOCAL_IPV4_ADDRESS,(uint8_t*)&sain->sin_addr,4); + } + break; +#ifdef WITH_IPV6 + case AF_INET6: + { + struct sockaddr_in6 * sain = (struct sockaddr_in6*)&a; + cwmsg_addelem(msg,CWMSGELEM_CAPWAP_LOCAL_IPV6_ADDRESS,(uint8_t*)&sain->sin6_addr,16); + } + break; +#endif + } +} + + diff --git a/src/capwap/cwmsg_addelem_mtu_discovery_padding.c b/src/capwap/cwmsg_addelem_mtu_discovery_padding.c new file mode 100644 index 00000000..58747414 --- /dev/null +++ b/src/capwap/cwmsg_addelem_mtu_discovery_padding.c @@ -0,0 +1,19 @@ +#include + +#include "capwap.h" +#include "conn.h" +#include "cwmsg.h" + +void cwmsg_addelem_mtu_discovery_padding(struct cwmsg * msg, struct conn* conn) +{ + int len = conn->mtu - (msg->msgelems-msg->buffer+msg->pos)-4; + + if (len < 0 ) + return; + + uint32_t val = CWMSGELEM_MTU_DISCOVERY_PADDING<<16|len; + *((uint32_t*)(msg->msgelems+msg->pos))=htonl(val); + memset(msg->msgelems+4+msg->pos,0xff,len); + msg->pos+=4+len; +} + diff --git a/src/capwap/cwmsg_addelem_result_code.c b/src/capwap/cwmsg_addelem_result_code.c new file mode 100644 index 00000000..6774bdab --- /dev/null +++ b/src/capwap/cwmsg_addelem_result_code.c @@ -0,0 +1,10 @@ + +#include "capwap.h" + +void cwmsg_addelem_result_code(struct cwmsg *msg,int rc) +{ + uint8_t c[4]; + *((uint32_t*)c)= htonl(rc); + cwmsg_addelem(msg,CWMSGELEM_RESULT_CODE,c,4); +} + diff --git a/src/capwap/cwmsg_addelem_wtp_board_data.c b/src/capwap/cwmsg_addelem_wtp_board_data.c new file mode 100644 index 00000000..b4ad563a --- /dev/null +++ b/src/capwap/cwmsg_addelem_wtp_board_data.c @@ -0,0 +1,37 @@ + +#include +#include + +#include "capwap.h" + + +void cwmsg_addelem_wtp_board_data(struct cwmsg * cwmsg, struct wtpinfo * wtpinfo) +{ + uint8_t msg[1030]; + *((uint32_t*)msg)=htonl(wtpinfo->vendor_id); + + int l; + int len=4; + + if (wtpinfo->model_no){ + l=strlen((char*)wtpinfo->model_no); + *((uint32_t*)(msg+len))=htonl(CWBOARDDATA_MODELNO<<16|l); + memcpy(msg+len+4,wtpinfo->model_no,l); + len+=l+4; + } + + if (wtpinfo->serial_no){ + l=strlen((char*)wtpinfo->serial_no); + *((uint32_t*)(msg+len))=htonl(CWBOARDDATA_SERIALNO<<16|l); + memcpy(msg+len+4,wtpinfo->serial_no,l); + len+=l+4; + } + + if (wtpinfo->macaddress){ + *((uint32_t*)(msg+len))=htonl(CWBOARDDATA_MACADDRESS<<16|wtpinfo->macaddress_len); + memcpy(msg+len+4,wtpinfo->macaddress,wtpinfo->macaddress_len); + len+=wtpinfo->macaddress_len+4; + } + + cwmsg_addelem(cwmsg,CWMSGELEM_WTP_BOARD_DATA,msg,len); +} diff --git a/src/capwap/cwmsg_addelem_wtp_descriptor.c b/src/capwap/cwmsg_addelem_wtp_descriptor.c new file mode 100644 index 00000000..abaf4b9d --- /dev/null +++ b/src/capwap/cwmsg_addelem_wtp_descriptor.c @@ -0,0 +1,57 @@ + +#include + +#include "capwap.h" + + +static inline int wtpdesc_addsubelem(uint8_t * dst,uint8_t type,uint32_t vendorid,uint8_t * str) +{ +// printf("add subelem\n"); + int l; + *((uint32_t*)(dst))=htonl(vendorid); +// printf("htonl done\n"); + l=strlen((char*)str); +// printf("strlne got %d\n",l); + *((uint32_t*)(dst+4))=htonl((type<<16)|l); +// printf("memcopy str %d\n",l); + memcpy(dst+8,str,l); + return l+8; +} + +void cwmsg_addelem_wtp_descriptor(struct cwmsg * cwmsg, struct wtpinfo * wtpinfo) +{ + uint8_t d[1024]; + int len=0; + + /* radios info */ + *(d)= wtpinfo->max_radios; + *(d+1)=wtpinfo->radios_in_use; + len=2; + + /* number of encryption elemnts */ + *(d+len)=1; + len+=1; + + /* encryption elements */ + *(d+len)=CWTH_WBID_IEEE80211; + uint16_t val = 0; + *((uint16_t*)(d+len+1))=htons(val); + len+=3; + + + /* hardware subelem*/ + len+=wtpdesc_addsubelem(d+len,CWMSGSUBELEM_WTP_DESCRIPTOR_HARDWARE_VERSION, + wtpinfo->hardware_vendor_id,wtpinfo->hardware_version); + + + /* software subelem*/ + len+=wtpdesc_addsubelem(d+len,CWMSGSUBELEM_WTP_DESCRIPTOR_SOFTWARE_VERSION, + wtpinfo->software_vendor_id,wtpinfo->software_version); + + /* bootloader subelem*/ + len+=wtpdesc_addsubelem(d+len,CWMSGSUBELEM_WTP_DESCRIPTOR_BOOTLOADER_VERSION, + wtpinfo->bootloader_vendor_id,wtpinfo->bootloader_version); + + + cwmsg_addelem(cwmsg,CWMSGELEM_WTP_DESCRIPTOR,d,len); +} diff --git a/src/capwap/cwmsg_addelem_wtp_radio_infos.c b/src/capwap/cwmsg_addelem_wtp_radio_infos.c new file mode 100644 index 00000000..8f591ec1 --- /dev/null +++ b/src/capwap/cwmsg_addelem_wtp_radio_infos.c @@ -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 . + +*/ + +#include "capwap.h" +#include "capwap_ieee80211.h" + +void cwmsg_addelem_wtp_radio_info(struct cwmsg * msg,struct radioinfo *radioinfo) +{ + uint8_t ri[5]; + *ri = radioinfo->rid; + *((uint32_t*)(ri+1))=htonl(radioinfo->type); + cwmsg_addelem(msg,CWMSGELEM_IEEE80211_WTP_RADIO_INFO,ri,5); +} + +void cwmsg_addelem_wtp_radio_infos(struct cwmsg * msg,struct wtpinfo * wtpinfo) +{ + int i; + for (i=1; i<30; i++) + { + if (wtpinfo->radioinfo[i].rid!=0) + cwmsg_addelem_wtp_radio_info(msg,&wtpinfo->radioinfo[i]); + } + +} diff --git a/src/capwap/cwmsg_init.c b/src/capwap/cwmsg_init.c new file mode 100644 index 00000000..4468741a --- /dev/null +++ b/src/capwap/cwmsg_init.c @@ -0,0 +1,62 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include +#include + +#include "capwap.h" + +#include "cwmsg.h" + + +void cwmsg_init(struct cwmsg * cwmsg, uint8_t *buffer, int type, int seqnum, struct radioinfo * radioinfo) +{ + int hlen=8; + cwmsg->buffer=buffer; + cwmsg->trnsprthdr=buffer; + +#ifdef WITH_RMAC_SUPPORT + int rmaclen; + if (radioinfo->rmac){ + rmaclen=(*radioinfo->rmac)+1; + memcpy(buffer+8,radioinfo->rmac,rmaclen); + cwmsg->flags=CWTH_FLAGS_M; + } + else + { + cwmsg->flags=0; + rmaclen=0; + } + hlen+=rmaclen; + if (hlen%4) + hlen = (hlen>>2)*4+4; +#endif + + + cwmsg->ctrlhdr=cwmsg->trnsprthdr+hlen; + cwmsg->msgelems=cwmsg->ctrlhdr+8; + + *((uint32_t*)(cwmsg->ctrlhdr))=htonl(type+CWIANA_ENTERPRISE_NUMBER*256); + + cwmsg->pos=0; + cwmsg->hlen=hlen/4; + cwmsg->rid=radioinfo->rid; + cwmsg->seqnum=seqnum; + cwmsg->type=type; +} + diff --git a/src/capwap/cwmsg_init_echo_request.c b/src/capwap/cwmsg_init_echo_request.c new file mode 100644 index 00000000..b5293304 --- /dev/null +++ b/src/capwap/cwmsg_init_echo_request.c @@ -0,0 +1,28 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include "capwap.h" +#include "conn.h" +#include "cwmsg.h" + +void cwmsg_init_echo_request(struct cwmsg * cwmsg,uint8_t *buffer,struct conn * conn, struct radioinfo * radioinfo) +{ + cwmsg_init(cwmsg,buffer,CWMSG_ECHO_REQUEST,conn_get_next_seqnum(conn),radioinfo); +} + + diff --git a/src/capwap/cwmsg_send.c b/src/capwap/cwmsg_send.c new file mode 100644 index 00000000..29a01c41 --- /dev/null +++ b/src/capwap/cwmsg_send.c @@ -0,0 +1,91 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include "capwap.h" + +#include "cwmsg.h" + + +int mtu = 564; + +int __old_cwmsg_send(struct cwmsg * cwmsg, int seqnum, int rid, struct conn * conn) +{ + uint32_t val; + + /* second dword of message control header */ + val = (seqnum<<24)|((cwmsg->pos+3)<<8); + *((uint32_t*)(cwmsg->ctrlhdr+4))=htonl(val); + + + +// int msglen = cwmsg->ctrlhdr-cwmsg->buffer+cwmsg->pos; + int msglen = cwmsg->pos+8; + + uint8_t * ptr = cwmsg->buffer; + int fragoffset = 0; + int hlen = cwmsg->hlen*4; + + + + int preamble = CW_VERSION | 0; + + + int wbid=CWTH_WBID_IEEE80211; + int packetlen = msglen+hlen; + + while (packetlen>mtu){ + val = (preamble << 24) | ((hlen/4)<<19) | (rid<<14) |(wbid<<9) | + CWTH_FLAGS_T | + CWTH_FLAGS_F | + cwmsg->flags; + *((uint32_t*)ptr)=htonl(val); + + val = conn->fragid<<16 | fragoffset<<3; + *((uint32_t*)(ptr+8))=htonl(val); + +// printf("Offset = %d\n",fragoffset); + + conn_send_packet(conn,ptr,mtu); + + ptr +=mtu-hlen; + fragoffset+=(mtu-hlen)/8; + + packetlen-=mtu-hlen; +// printf("Packelen=%d\n",packetlen); + + } + + val = (preamble << 24) | ((hlen/4)<<19) | (rid<<14) |(wbid<<9) | + CWTH_FLAGS_T|cwmsg->flags; + + if (fragoffset) + val |= CWTH_FLAGS_F | CWTH_FLAGS_L; + + +// printf("Setting first byte %08X\n",val); + *((uint32_t*)ptr)=htonl(val); + + + val = conn->fragid<<16 | fragoffset<<3; + *((uint32_t*)(ptr+4))=htonl(val); + + return conn_send_packet(conn,cwmsg->buffer,msglen-fragoffset*8+hlen); +} + + + diff --git a/src/capwap/cwmsg_set_control_header.c b/src/capwap/cwmsg_set_control_header.c new file mode 100644 index 00000000..0ba2ed8a --- /dev/null +++ b/src/capwap/cwmsg_set_control_header.c @@ -0,0 +1,13 @@ + +#include "cwmsg.h" + +void cwmsg_set_control_header(struct cwmsg * cwmsg,int msgtype, int seqnum) +{ + uint32_t val; + val = htonl(msgtype); + *((uint32_t*)(cwmsg->ctrlhdr))=htonl(val); + val = (seqnum<<24)|(cwmsg->pos<<8); + *((uint32_t*)(cwmsg->ctrlhdr+4))=htonl(val); +} + + diff --git a/src/capwap/cwread_discovery_response.c b/src/capwap/cwread_discovery_response.c new file mode 100644 index 00000000..f7453548 --- /dev/null +++ b/src/capwap/cwread_discovery_response.c @@ -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 . + +*/ + +#include +#include +#include +#include + +#include "capwap.h" +#include "acinfo.h" +#include "cw_util.h" +#include "cw_log.h" + +#include +#include + + + + +static int acinfo_readelem_discovery_resp(void * a,int type,uint8_t* msgelem,int len) +{ + + struct ac_info * acinfo = (struct ac_info *)a; + cw_log_debug1("Process discovery resp msgelem, type=%d, len=%d\n",type,len); + + if (acinfo_readelem_ac_descriptor(acinfo,type,msgelem,len)) + return 1; + + if (acinfo_readelem_ac_name(acinfo,type,msgelem,len)) + return 1; + + if (acinfo_readelem_ctrl_ip_addr(acinfo,type,msgelem,len)) + return 1; + + return 0; +} + + + +void cwread_discovery_response(struct ac_info * acinfo, uint8_t * msg, int len) +{ + cw_foreach_msgelem(msg,len,acinfo_readelem_discovery_resp,acinfo); +} + + + diff --git a/src/capwap/cwread_join_response.c b/src/capwap/cwread_join_response.c new file mode 100644 index 00000000..81b4deb5 --- /dev/null +++ b/src/capwap/cwread_join_response.c @@ -0,0 +1,58 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include "capwap.h" +#include "acinfo.h" + +#include "cw_log.h" +#include "cw_util.h" + +static int acinfo_readelem_join_resp(void * a,int type,uint8_t* msgelem,int len) +{ + + struct ac_info * acinfo = (struct ac_info *)a; + cw_log_debug1("Process join resp msgelem, type=%d, len=%d\n",type,len); + + if (acinfo_readelem_ecn_support(acinfo,type,msgelem,len)) + return 1; + + if (acinfo_readelem_ac_descriptor(acinfo,type,msgelem,len)) + return 1; + + if (acinfo_readelem_ac_name(acinfo,type,msgelem,len)) + return 1; + + if (acinfo_readelem_ctrl_ip_addr(acinfo,type,msgelem,len)) + return 1; + + if (acinfo_readelem_cw_local_ip_addr(acinfo,type,msgelem,len)) + return 1; + + return 0; +} + + + +void cwread_join_response(struct ac_info * acinfo, uint8_t * msg, int len) +{ + cw_log_debug1("Reading join response"); + cw_foreach_msgelem(msg,len,acinfo_readelem_join_resp,acinfo); +} + + + diff --git a/src/capwap/cwrmsg.h b/src/capwap/cwrmsg.h new file mode 100644 index 00000000..3ee7b971 --- /dev/null +++ b/src/capwap/cwrmsg.h @@ -0,0 +1,18 @@ +#ifndef __CWRMSG_H +#define __CWRMSG_H + +struct cwrmsg{ + int rid; + int wbid; + uint8_t * msgelems; + int msgelems_len; + int type; + int seqnum; + int msglen; +#ifdef WITH_RMAC_SUPPORT + uint8_t * rmac; +#endif + +}; + +#endif diff --git a/src/capwap/cwsend_discovery_request.c b/src/capwap/cwsend_discovery_request.c new file mode 100644 index 00000000..3ee53d82 --- /dev/null +++ b/src/capwap/cwsend_discovery_request.c @@ -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 . + +*/ + +#include "capwap.h" +#include "conn.h" +#include "cwmsg.h" + +int cwsend_discovery_request(struct conn * conn,struct radioinfo * radioinfo,struct wtpinfo * wtpinfo) +{ + uint8_t buffer[CWMSG_MAX_SIZE]; + struct cwmsg cwmsg; + + cwmsg_init(&cwmsg,buffer,CWMSG_DISCOVERY_REQUEST,conn_get_next_seqnum(conn),radioinfo); + + cwmsg_addelem(&cwmsg,CWMSGELEM_DISCOVERY_TYPE,&wtpinfo->discovery_type,sizeof(uint8_t)); + cwmsg_addelem_wtp_board_data(&cwmsg,wtpinfo); + cwmsg_addelem_wtp_descriptor(&cwmsg,wtpinfo); + cwmsg_addelem(&cwmsg,CWMSGELEM_WTP_FRAME_TUNNEL_MODE,&wtpinfo->frame_tunnel_mode,sizeof(uint8_t)); + cwmsg_addelem(&cwmsg,CWMSGELEM_WTP_MAC_TYPE,&wtpinfo->mac_type,sizeof(uint8_t)); + cwmsg_addelem_wtp_radio_infos(&cwmsg,wtpinfo); + cwmsg_addelem_mtu_discovery_padding(&cwmsg,conn); + + return conn_send_cwmsg(conn,&cwmsg); +} diff --git a/src/capwap/cwsend_discovery_response.c b/src/capwap/cwsend_discovery_response.c new file mode 100644 index 00000000..1a3e4b1f --- /dev/null +++ b/src/capwap/cwsend_discovery_response.c @@ -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 . + +*/ + + +#include + +#include "capwap.h" +#include "conn.h" +#include "cwmsg.h" + +int conn_send_response(struct conn * conn,struct cwmsg * cwmsg,int seqnum) +{ + conn->last_response = cwmsg; +// conn->last_response_seqnum=seqnum; +// cwmsg_send(cwmsg,seqnum,rid,conn); + conn_send_cwmsg(conn,cwmsg); //,seqnum); + return 1; +} + +void cwsend_discovery_response(struct conn * conn,int seqnum, struct radioinfo * radioinfo, struct ac_info * acinfo, struct wtpinfo * wtpinfo) +{ + struct cwmsg * cwmsg = &conn->swm; + cwmsg_init(cwmsg,conn->buffer,CWMSG_DISCOVERY_RESPONSE,seqnum,radioinfo); + + cwmsg_addelem_ac_descriptor(cwmsg,acinfo); + cwmsg_addelem(cwmsg,CWMSGELEM_AC_NAME,(uint8_t*)acinfo->ac_name,strlen(acinfo->ac_name)); + cwmsg_addelem_wtp_radio_infos(cwmsg,wtpinfo); + cwmsg_addelem_ctrl_ip_addrs(cwmsg,acinfo); + + conn_send_response(conn,cwmsg,seqnum); +} + diff --git a/src/capwap/cwsend_echo_request.c b/src/capwap/cwsend_echo_request.c new file mode 100644 index 00000000..88a07440 --- /dev/null +++ b/src/capwap/cwsend_echo_request.c @@ -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 . + +*/ + + +#include "capwap.h" +#include "conn.h" +#include "cwmsg.h" + + +int cwsend_echo_request(struct conn * conn,struct radioinfo * radioinfo) //,struct wtpinfo * wtpinfo) +{ + uint8_t buffer[CWMSG_MAX_SIZE]; + struct cwmsg cwmsg; + +// cwmsg_init(&cwmsg,buffer,CWMSG_ECHO_REQUEST,conn_get_next_seqnum(conn),radioinfo); + cwmsg_init_echo_request(&cwmsg,buffer,conn,radioinfo); + return conn_send_cwmsg(conn,&cwmsg); +} diff --git a/src/capwap/cwsend_echo_response.c b/src/capwap/cwsend_echo_response.c new file mode 100644 index 00000000..73e75147 --- /dev/null +++ b/src/capwap/cwsend_echo_response.c @@ -0,0 +1,17 @@ +#include "capwap.h" +#include "conn.h" +#include "cwmsg.h" + +int cwsend_echo_response(struct conn * conn,int seqnum,struct radioinfo * radioinfo) //,struct wtpinfo * wtpinfo) +{ + //uint8_t buffer[CWMSG_MAX_SIZE]; + struct cwmsg * cwmsg = &conn->swm; + cwmsg_init(cwmsg,conn->buffer,CWMSG_ECHO_RESPONSE,seqnum,radioinfo); + + conn_send_response(conn,cwmsg,seqnum); + return 1; + + //cwmsg_init(&cwmsg,buffer,CWMSG_ECHO_REQUEST,conn_get_next_seqnum(conn),radioinfo); + // return conn_send_cwmsg(conn,&cwmsg); + +} diff --git a/src/capwap/cwsend_join_request.c b/src/capwap/cwsend_join_request.c new file mode 100644 index 00000000..5872cd27 --- /dev/null +++ b/src/capwap/cwsend_join_request.c @@ -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 . + +*/ + +#include + +#include "capwap.h" +#include "conn.h" +#include "cwmsg.h" + +int cwsend_join_request(struct conn * conn,struct radioinfo * radioinfo,struct wtpinfo * wtpinfo) +{ + uint8_t buffer[CWMSG_MAX_SIZE]; + struct cwmsg cwmsg; + + cwmsg_init(&cwmsg,buffer,CWMSG_JOIN_REQUEST,conn_get_next_seqnum(conn),radioinfo); + + cwmsg_addelem(&cwmsg,CWMSGELEM_LOCATION_DATA,wtpinfo->location,strlen((char*)wtpinfo->location)); + cwmsg_addelem_wtp_board_data(&cwmsg,wtpinfo); + cwmsg_addelem_wtp_descriptor(&cwmsg,wtpinfo); + cwmsg_addelem(&cwmsg,CWMSGELEM_WTP_NAME,wtpinfo->name,strlen((char*)wtpinfo->name)); + + if (wtpinfo->session_id_len>0){ + cwmsg_addelem(&cwmsg,CWMSGELEM_SESSION_ID,wtpinfo->session_id,wtpinfo->session_id_len); + } + + cwmsg_addelem(&cwmsg,CWMSGELEM_WTP_FRAME_TUNNEL_MODE,&wtpinfo->frame_tunnel_mode,sizeof(uint8_t)); + cwmsg_addelem(&cwmsg,CWMSGELEM_WTP_MAC_TYPE,&wtpinfo->mac_type,sizeof(uint8_t)); + cwmsg_addelem_wtp_radio_infos(&cwmsg,wtpinfo); + + cwmsg_addelem(&cwmsg,CWMSGELEM_ECN_SUPPORT,&wtpinfo->ecn_support,sizeof(uint8_t)); + cwmsg_addelem_cw_local_ip_addr(&cwmsg,conn); + + uint16_t l = htons(wtpinfo->max_msg_len); + cwmsg_addelem(&cwmsg,CWMSGELEM_MAXIMUM_MESSAGE_LENGTH,(uint8_t*)&l,sizeof(l)); + + return conn_send_cwmsg(conn,&cwmsg); +} diff --git a/src/capwap/cwsend_join_response.c b/src/capwap/cwsend_join_response.c new file mode 100644 index 00000000..0bcf42c3 --- /dev/null +++ b/src/capwap/cwsend_join_response.c @@ -0,0 +1,26 @@ + +#include + + +#include "capwap.h" +#include "conn.h" + +void cwsend_join_response(struct conn * conn,int seqnum, int rc, struct radioinfo * radioinfo, struct ac_info * acinfo, struct wtpinfo * wtpinfo) +{ + struct cwmsg * cwmsg = &conn->swm; + cwmsg_init(cwmsg,conn->buffer,CWMSG_JOIN_RESPONSE,seqnum,radioinfo); + + cwmsg_addelem_result_code(cwmsg,rc); + cwmsg_addelem_ac_descriptor(cwmsg,acinfo); + + cwmsg_addelem(cwmsg,CWMSGELEM_AC_NAME,acinfo->ac_name,strlen((char*)acinfo->ac_name)); + cwmsg_addelem(cwmsg,CWMSGELEM_ECN_SUPPORT,&acinfo->ecn_support,sizeof(uint8_t)); + cwmsg_addelem_ctrl_ip_addrs(cwmsg,acinfo); + cwmsg_addelem_cw_local_ip_addr(cwmsg,conn); + + conn_send_response(conn,cwmsg,seqnum); + +} + + + diff --git a/src/capwap/dtls.h b/src/capwap/dtls.h new file mode 100644 index 00000000..90319637 --- /dev/null +++ b/src/capwap/dtls.h @@ -0,0 +1,30 @@ +/* + 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 . + +*/ + +#ifndef __DTLS_H +#define __DTLS_H + +#include "dtls_openssl.h" + +#define dtls_init dtls_openssl_init +#define dtls_accept dtls_openssl_accept +#define dtls_connect dtls_openssl_connect +#define dtls_shutdown dtls_openssl_shutdown + +#endif + diff --git a/src/capwap/dtls_openssl.c b/src/capwap/dtls_openssl.c new file mode 100644 index 00000000..2c17f588 --- /dev/null +++ b/src/capwap/dtls_openssl.c @@ -0,0 +1,379 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ +#include + +#include +#include +#include + + +#include "dtls_openssl.h" + +#include "cw_log.h" +#include "conn.h" + + +int dtls_openssl_init() +{ + cw_log_debug0("Init ssl library"); + SSL_load_error_strings(); + return SSL_library_init(); +} + + +int dtls_openssl_log_error_queue(const char *txt) +{ + int e = ERR_get_error(); + if (e==0) + return 0; + + char errstr[256]; + while (e!=0){ + ERR_error_string(e,errstr); + cw_log(LOG_ERR,"%s - %s",txt,errstr); + e = ERR_get_error(); + } + return 1; +} + +int dtls_openssl_log_error(SSL * ssl, int rc, const char *txt) +{ + int en = errno; /* save errno */ + + if (!ssl){ + return dtls_openssl_log_error_queue(txt); + } + + int e; + e = SSL_get_error(ssl,rc); + switch (e){ + case SSL_ERROR_ZERO_RETURN: + break; + case SSL_ERROR_SYSCALL: + if (!dtls_openssl_log_error_queue(txt)){ + /* error queu was empty */ + if (rc<0){ + cw_log(LOG_ERR,"%s - %s",txt,strerror(en)); + return 1; + } + + cw_log(LOG_ERR,"%s - EOF observed",txt); + return 1; + } + + } + return 0; +} + + +void dtls_openssl_data_destroy(struct dtls_openssl_data * d){ + if (!d) + return; + + if (d->ssl) + SSL_free(d->ssl); + + if (d->ctx) + SSL_CTX_free(d->ctx); + + + free(d); +} + + +struct dtls_openssl_data * dtls_openssl_data_create(struct conn * conn, const SSL_METHOD * method, BIO_METHOD * bio) +{ + struct dtls_openssl_data * d = malloc(sizeof(struct dtls_openssl_data)); + if (!d) + return 0; + memset(d,0,sizeof(struct dtls_openssl_data)); + + d->ctx = SSL_CTX_new(method); + if (!d->ctx){ + dtls_openssl_data_destroy(d); + return 0; + } + + SSL_CTX_set_read_ahead(d->ctx, 1); +// int rc = SSL_CTX_set_cipher_list(d->ctx, "PSK-AES128-CBC-SHA"); + + //int rc = SSL_CTX_set_cipher_list(d->ctx, "PSiaK-AXES128-C5BC-SaHA"); + int rc = SSL_CTX_set_cipher_list(d->ctx, conn->dtls_cipher); + + + if (!rc){ + dtls_openssl_log_error(0,rc,"DTLS:"); + dtls_openssl_data_destroy(d); + return 0; + } + + d->ssl = SSL_new(d->ctx); + if (!d->ssl){ + dtls_openssl_data_destroy(d); + return 0; + } + + d->bio = BIO_new(bio); + d->bio->ptr = conn; + SSL_set_bio(d->ssl, d->bio, d->bio); + + return d; +} + + +/* + * Convert the PSK key (psk_key) in ascii to binary (psk). + */ +int dtls_openssl_psk_key2bn(const char *psk_key, unsigned char *psk, unsigned int max_psk_len) { + + unsigned int psk_len = 0; + int ret; + BIGNUM *bn = NULL; + + ret = BN_hex2bn(&bn, psk_key); + if (!ret) { + + cw_log(LOG_ERR,"Could not convert PSK key '%s' to BIGNUM\n", psk_key); + if (bn) + BN_free(bn); + return 0; + } + + if (BN_num_bytes(bn) > max_psk_len) { + + cw_log(LOG_ERR,"psk buffer of callback is too small (%d) for key (%d)\n", + max_psk_len, BN_num_bytes(bn)); + BN_free(bn); + return 0; + } + psk_len = BN_bn2bin(bn, psk); + BN_free(bn); + + if (psk_len < 0) + goto out_err; + return psk_len; +out_err: + return 0; +} + + +#include +//#include +#include + +int dtls_openssl_shutdown(struct conn *conn) +{ + conn->write = conn->send_packet; + conn->read = conn->recv_packet; + + struct dtls_openssl_data * d = (struct dtls_openssl_data*)conn->dtls_data; + if (!d) + return 0; + + + + + + SSL_shutdown(d->ssl); + dtls_openssl_data_destroy(d); + + conn->dtls_data=0; + + return 1; +} + + +int cookie_initialized=0; +#define COOKIE_SECRET_LENGTH 16 +unsigned char cookie_secret[COOKIE_SECRET_LENGTH]; + +int dtls_openssl_generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len) + { + unsigned char *buffer, result[EVP_MAX_MD_SIZE]; + unsigned int length = 0, resultlength; + union { + struct sockaddr_storage ss; + struct sockaddr_in6 s6; + struct sockaddr_in s4; + } peer; + + /* Initialize a random secret */ + if (!cookie_initialized) + { + if (!RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH)) + { + printf("error setting random cookie secret\n"); + return 0; + } + cookie_initialized = 1; + } + + /* Read peer information */ + (void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer); + + /* Create buffer with peer's address and port */ + length = 0; + switch (peer.ss.ss_family) { + case AF_INET: + length += sizeof(struct in_addr); + break; + case AF_INET6: + length += sizeof(struct in6_addr); + break; + default: + OPENSSL_assert(0); + break; + } + length += sizeof(in_port_t); + buffer = (unsigned char*) OPENSSL_malloc(length); + + if (buffer == NULL) + { + printf("out of memory\n"); + return 0; + } + + switch (peer.ss.ss_family) { + case AF_INET: + memcpy(buffer, + &peer.s4.sin_port, + sizeof(in_port_t)); + memcpy(buffer + sizeof(peer.s4.sin_port), + &peer.s4.sin_addr, + sizeof(struct in_addr)); + break; + case AF_INET6: + memcpy(buffer, + &peer.s6.sin6_port, + sizeof(in_port_t)); + memcpy(buffer + sizeof(in_port_t), + &peer.s6.sin6_addr, + sizeof(struct in6_addr)); + break; + default: + OPENSSL_assert(0); + break; + } + + /* Calculate HMAC of buffer using the secret */ + HMAC(EVP_sha1(), (const void*) cookie_secret, COOKIE_SECRET_LENGTH, + (const unsigned char*) buffer, length, result, &resultlength); + OPENSSL_free(buffer); + + memcpy(cookie, result, resultlength); + *cookie_len = resultlength; + + return 1; +} + + +int dtls_openssl_verify_cookie(SSL *ssl, unsigned char *cookie, unsigned int cookie_len) + { + unsigned char *buffer, result[EVP_MAX_MD_SIZE]; + unsigned int length = 0, resultlength; + union { + struct sockaddr_storage ss; + struct sockaddr_in6 s6; + struct sockaddr_in s4; + } peer; + + /* If secret isn't initialized yet, the cookie can't be valid */ + if (!cookie_initialized) + return 0; + + /* Read peer information */ + (void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer); + + /* Create buffer with peer's address and port */ + length = 0; + switch (peer.ss.ss_family) { + case AF_INET: + length += sizeof(struct in_addr); + break; + case AF_INET6: + length += sizeof(struct in6_addr); + break; + default: + OPENSSL_assert(0); + break; + } + length += sizeof(in_port_t); + buffer = (unsigned char*) OPENSSL_malloc(length); + + if (buffer == NULL) + { + printf("out of memory\n"); + return 0; + } + + switch (peer.ss.ss_family) { + case AF_INET: + memcpy(buffer, + &peer.s4.sin_port, + sizeof(in_port_t)); + memcpy(buffer + sizeof(in_port_t), + &peer.s4.sin_addr, + sizeof(struct in_addr)); + break; + case AF_INET6: + memcpy(buffer, + &peer.s6.sin6_port, + sizeof(in_port_t)); + memcpy(buffer + sizeof(in_port_t), + &peer.s6.sin6_addr, + sizeof(struct in6_addr)); + break; + default: + OPENSSL_assert(0); + break; + } + + /* Calculate HMAC of buffer using the secret */ + HMAC(EVP_sha1(), (const void*) cookie_secret, COOKIE_SECRET_LENGTH, + (const unsigned char*) buffer, length, result, &resultlength); + OPENSSL_free(buffer); + + if (cookie_len == resultlength && memcmp(result, cookie, resultlength) == 0) + return 1; + + return 0; + } + +struct pass_info { + union { + struct sockaddr_storage ss; + struct sockaddr_in6 s6; + struct sockaddr_in s4; + } server_addr, client_addr; + SSL *ssl; +}; + + + +int dtls_openssl_read(struct conn * conn, uint8_t *buffer, int len) +{ + struct dtls_openssl_data * d = conn->dtls_data; + return SSL_read(d->ssl,buffer,len); +} + +int dtls_openssl_write(struct conn * conn, const uint8_t *buffer, int len) +{ + struct dtls_openssl_data * d = conn->dtls_data; + return SSL_write(d->ssl,buffer,len); +} + diff --git a/src/capwap/dtls_openssl.h b/src/capwap/dtls_openssl.h new file mode 100644 index 00000000..ab1cf579 --- /dev/null +++ b/src/capwap/dtls_openssl.h @@ -0,0 +1,48 @@ +#ifndef __DTLS_OPENSLL_H +#define __DTLS_OPENSSL_H + +#include + +#include + +#include "conn.h" + +struct dtls_openssl_data{ + SSL_CTX * ctx; + SSL * ssl; + BIO * bio; + + uint8_t buffer[2048]; + int len; + int pos; +}; + +extern int dtls_openssl_init(); +//extern struct dtls_openssl_data * dtls_openssl_data_create(const SSL_METHOD * method ); +//struct dtls_openssl_data * dtls_openssl_data_create(const SSL_METHOD * method, const BIO_METHOD * bio); +struct dtls_openssl_data * dtls_openssl_data_create(struct conn * conn, const SSL_METHOD * method, BIO_METHOD * bio); +extern int dtls_openssl_psk_key2bn(const char *psk_key, unsigned char *psk, unsigned int max_psk_len); +extern int dtls_openssl_generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len); +extern int dtls_openssl_verify_cookie(SSL *ssl, unsigned char *cookie, unsigned int cookie_len); + +extern int dtls_openssl_read(struct conn * conn, uint8_t *buffer, int len); +extern int dtls_openssl_write(struct conn * conn, const uint8_t *buffer, int len); +extern int dtls_openssl_connect(struct conn * conn); + +extern int dtls_openssl_log_error(SSL * ssl, int rc, const char *txt); + + + + +extern int dtls_openssl_bio_puts(BIO *bp, const char *str); +extern int dtls_openssl_bio_read(BIO *b, char *out, int maxlen); +extern int dtls_openssl_bio_write(BIO *b, const char *data, int len); +extern long dtls_openssl_bio_ctrl(BIO *b, int cmd, long num, void *ptr); +extern int dtls_openssl_bio_new(BIO *bi); +extern int dtls_openssl_bio_free(BIO *bio); + + +extern BIO *bbb; + + +#endif diff --git a/src/capwap/dtls_openssl_accept.c b/src/capwap/dtls_openssl_accept.c new file mode 100644 index 00000000..41041d5c --- /dev/null +++ b/src/capwap/dtls_openssl_accept.c @@ -0,0 +1,160 @@ +#include + +#include "dtls_openssl.h" +#include "conn.h" + +#include "cw_log.h" + + + +static BIO_METHOD bio_methods = { + BIO_TYPE_DGRAM, + "cw packet", + dtls_openssl_bio_write, + dtls_openssl_bio_read, + dtls_openssl_bio_puts, + NULL, // dgram_gets + dtls_openssl_bio_ctrl, + dtls_openssl_bio_new, + dtls_openssl_bio_free, + NULL, +}; + + + +static unsigned int psk_server_cb(SSL *ssl,const char *identity, unsigned char * psk, unsigned int max_psk_len) +{ + BIO * b = SSL_get_rbio(ssl); + struct conn * conn = b->ptr; + +// printf("PSK_CB: %s\n",identity); +// printf("Conn psk : %s\n",conn->dtls_psk); +// printf("Max dtls psk len %i\n",max_psk_len); + + +// return dtls_openssl_psk_key2bn(conn->dtls_psk, psk, max_psk_len); + + + int l = conn->dtls_psk_len < max_psk_len ? conn->dtls_psk_len : max_psk_len; + +// printf("PSK return l %d\n",l); + memcpy(psk,conn->dtls_psk,l); + return l; +} + + + +int dtls_openssl_accept(struct conn * conn) +{ + if (!conn->dtls_data) + conn->dtls_data = dtls_openssl_data_create(conn,DTLSv1_server_method(),&bio_methods); + + struct dtls_openssl_data * d = (struct dtls_openssl_data*)conn->dtls_data; + if (!d) + return 0; + + SSL_set_psk_server_callback( d->ssl, psk_server_cb); + + int rc; +// do{ + int i; + for (i=0; i<5; i++){ + rc = SSL_accept(d->ssl); + if (rc==0){ + int e; + e = SSL_get_error(d->ssl,rc); + switch (e){ + case SSL_ERROR_SYSCALL: + printf("syscall EOF!\n"); + break; + } + + + + char errstr[256]; + + e = ERR_get_error(); + while (e!=0){ + ERR_error_string(e,errstr); + cw_log(LOG_ERR,"SSL_accept (e) - %s",e,errstr); + e = ERR_get_error(); + } + + + continue; + } + if (rc == 1) + { +// printf("Juhu!\n"); + conn->read = dtls_openssl_read; + conn->write = dtls_openssl_write; + return 1; + } + + + } + + return 0; + +// } while (rc == 0 ); + + if (rc != 1){ + char errstr[256]; + int e = ERR_get_error(); + ERR_error_string(e,errstr); + cw_log(LOG_ERR,"SSL_accept %s",errstr); + return 0; + } + + + return 1; + +/* + struct dtls_openssl_data * data = dtls_openssl_data_new(); + if (!data) + return 0; + + SSL_CTX * ctx = dtls_openssl_create_ctx(DTLSv1_server_method()); + if (!ctx){ + free (data); + return 0; + } + + + + + +// dtls_init(conn,DTLSv1_server_method()); + + struct dtls_data * dtls_data = conn->dtls_data; + SSL * ssl = dtls_data->ssl; + +//i printf("bio connected\n"); +// BIO_ctrl(SSL_get_rbio(ssl), BIO_CTRL_DGRAM_SET_CONNECTED, 0, NULLi //&pinfo->client_addr.ss); +// printf("bio connected done\n"); + int rc; + printf("doing accepz\n"); +// do { + rc = SSL_accept(ssl); + printf("accept again\n"); +// } while(rc==0); + perror ("ERRP"); + + printf("SSL accept rc %i\n",rc); + int e = ERR_get_error(); + printf ("THE E: %i\n",e); + + + char es[499]; + ERR_error_string(e,es); + printf ("ES: %s\n",es); + + + rc = SSL_get_error(ssl,rc); + printf("ERROR RC: %08X\n",rc); + + exit(9); +*/ +} + + diff --git a/src/capwap/dtls_openssl_bio.c b/src/capwap/dtls_openssl_bio.c new file mode 100644 index 00000000..118da023 --- /dev/null +++ b/src/capwap/dtls_openssl_bio.c @@ -0,0 +1,171 @@ + +#include +#include "dtls_openssl.h" + +#include "conn.h" + +int dtls_openssl_bio_write(BIO *b, const char *data, int len) +{ +// printf("bio_write %p %d",data,len); + + struct conn * conn = b->ptr; + uint8_t buffer[2048]; + *((uint32_t*)buffer)=htonl(1<<24); + memcpy(buffer+4,data,len); + int rc = conn->send_packet(conn,buffer,len+4); + if (rc<0) + return rc; + return rc-4; +} + + +int dtls_openssl_bio_read(BIO *b, char *out, int maxlen) +{ +// printf("READER WHANT: %d\n",maxlen); + + struct conn * conn = b->ptr; + struct dtls_openssl_data * dtls_data = conn->dtls_data; +// int len; + if (dtls_data->len==0){ + int len = conn->recv_packet(conn,dtls_data->buffer,2048); + if (len<4) + return 0; + dtls_data->len=len-4; + dtls_data->pos=4; +// printf("DTLS_DATA_LEN: %d\n",dtls_data->len); + } + + if (dtls_data->len > maxlen) + { + memcpy(out,dtls_data->buffer+dtls_data->pos,maxlen); + dtls_data->len-=maxlen; + dtls_data->pos+=maxlen; +// printf("Return %d, %d beyes left\n",maxlen,dtls_data->len); + return maxlen; + + } + +// printf("Return rest = %d\n",dtls_data->len); + memcpy(out,dtls_data->buffer+dtls_data->pos,dtls_data->len); + int ret = dtls_data->len; + dtls_data->len=0; + return ret; +} + + + +int dtls_openssl_bio_new(BIO *bi) +{ + bi->init = 1; + bi->num = 0; + bi->flags = 0; + bi->ptr = NULL; + return 1; +} + + + +int dtls_openssl_bio_puts(BIO *b, const char *str) +{ + return dtls_openssl_bio_write(b, str, strlen(str)); +} + +int dtls_openssl_bio_free(BIO *bio) +{ + printf("Bio free\n"); + if (bio == NULL) + return 0; + return 1; +} + + + +long dtls_openssl_bio_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret = 1; +// long sockopt_val = 0; +// unsigned int sockopt_len = 0; +// BIO_memory_data* pData = (BIO_memory_data*)b->ptr; +// +// printf("BIO CONTROL \n"); +// exit(1); + + switch (cmd) + { + case BIO_CTRL_RESET: + case BIO_CTRL_EOF: + ret = 0; + break; + + case BIO_CTRL_INFO: + ret = 0; + break; + + case BIO_CTRL_GET_CLOSE: + ret = 0; + break; + + case BIO_CTRL_SET_CLOSE: + break; + + case BIO_CTRL_WPENDING: + ret = 0; + break; + + case BIO_CTRL_PENDING: + ret = 0; + break; + + case BIO_CTRL_DUP: + ret = 1; + break; + + case BIO_CTRL_FLUSH: + ret = 1; + break; + + case BIO_CTRL_PUSH: + ret = 0; + break; + + case BIO_CTRL_POP: + ret = 0; + + case BIO_CTRL_DGRAM_QUERY_MTU: + { + ret = 1000; + +/* sockopt_len = sizeof(sockopt_val); + if ((ret = getsockopt(pData->sock, IPPROTO_IP, IP_MTU, (void *)&sockopt_val, &sockopt_len)) < 0 || sockopt_val < 0) + { + ret = 0; + } + else + { + pData->nMtu = sockopt_val; + ret = sockopt_val; + } + + break; + +*/ } + + case BIO_CTRL_DGRAM_GET_MTU: + ret = 1000; +// ret = pData->nMtu; + break; + + case BIO_CTRL_DGRAM_SET_MTU: +// pData->nMtu = num; +// ret = num; + break; + + default: + ret = 0; + break; + } + + return ret; +} + + diff --git a/src/capwap/dtls_openssl_connect.c b/src/capwap/dtls_openssl_connect.c new file mode 100644 index 00000000..d2478644 --- /dev/null +++ b/src/capwap/dtls_openssl_connect.c @@ -0,0 +1,98 @@ +#include + +#include "dtls_openssl.h" +#include "cw_log.h" + +static BIO_METHOD bio_methods = { + BIO_TYPE_DGRAM, + "cw packet", + dtls_openssl_bio_write, + dtls_openssl_bio_read, + dtls_openssl_bio_puts, + NULL, // dgram_gets + dtls_openssl_bio_ctrl, + dtls_openssl_bio_new, + dtls_openssl_bio_free, + NULL, +}; + + +static unsigned int psk_client_cb(SSL *ssl, + const char *hint, + char *identity, + unsigned int max_identity_len, + unsigned char *psk, + unsigned int max_psk_len) { + + BIO * b = SSL_get_rbio(ssl); + struct conn * conn = b->ptr; + +// printf("KEYY: %s\n",conn->dtls_psk); + + snprintf(identity, max_identity_len, "CLient_identity"); + + int l = conn->dtls_psk_len < max_psk_len ? conn->dtls_psk_len : max_psk_len; + memcpy(psk,conn->dtls_psk,l); + return l; + +} + + +int dtls_openssl_connect(struct conn * conn) +{ + if (!conn->dtls_data) + conn->dtls_data = dtls_openssl_data_create(conn,DTLSv1_client_method(),&bio_methods); + + struct dtls_openssl_data * d = (struct dtls_openssl_data*)conn->dtls_data; + if (!d) + return 0; + + SSL_set_psk_client_callback( d->ssl, psk_client_cb); + + char errstr[256]; + int rc; + do{ + rc = SSL_connect(d->ssl); + + +/* if (rc <= 0){ + int e; + e = SSL_get_error(d->ssl,rc); + printf("Get Err %i\n",e); + + + printf("SSL Connect rc = %i\n",rc); + e = ERR_get_error(); + ERR_error_string(e,errstr); + cw_log(LOG_ERR,"SSL_connect %s",errstr); + + + + + } + +*/ + + if(rc==1){ + conn->read = dtls_openssl_read; + conn->write = dtls_openssl_write; + return 1; + } + + + rc = dtls_openssl_log_error(d->ssl,rc,"DTLS connect"); + + } while (rc == 0 ); + +// printf("DTLS connect RC: %i\n",rc); + +// int e = ERR_get_error(); +// ERR_error_string(e,errstr); +// cw_log(LOG_ERR,"SSL_accept %s",errstr); + + + return 0; +} + + + diff --git a/src/capwap/dtls_openssl_init.c b/src/capwap/dtls_openssl_init.c new file mode 100644 index 00000000..55421a8d --- /dev/null +++ b/src/capwap/dtls_openssl_init.c @@ -0,0 +1,41 @@ + + + +int dtls_openssl_init(struct conn * conn,const SSL_METHOD * method) +{ + conn->dtls_data = malloc(sizeof(struct dtls_data)); + struct dtls_data * dtls_data = conn->dtls_data; + if (!dtls_data) + return 0; + dtls_data->pos=0; + dtls_data->len=0; + + + SSL_CTX *ctx; + SSL *ssl; + BIO *bio = BIO_new(&bio_methods); + bio->ptr = conn; + printf("Assigning conn %p\n",bio->ptr); + + OpenSSL_add_ssl_algorithms(); + SSL_load_error_strings(); + + printf("Getting CTX\n"); + ctx = SSL_CTX_new(method); //DTLSv1_client_method()); + printf("CTX: %p\n",ctx); + int rc = SSL_CTX_set_cipher_list(ctx, "PSK-AES128-CBC-SHA"); + printf("Set cipher RC: %d\n",rc); + SSL_CTX_set_psk_client_callback( ctx, psk_cb); + SSL_CTX_set_psk_server_callback( ctx, psk_server_cb); + SSL_CTX_set_read_ahead(ctx, 1); + SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie); + SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie); + + ssl = SSL_new(ctx); + SSL_set_bio(ssl, bio, bio); + printf("New rc %p\n",ssl); + dtls_data->ssl=ssl; + return 0; +} + + diff --git a/src/capwap/fragman.c b/src/capwap/fragman.c new file mode 100644 index 00000000..a7520707 --- /dev/null +++ b/src/capwap/fragman.c @@ -0,0 +1,203 @@ +/* + 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 . + +*/ + + +/* + * This file implements a simple fragment management system + * for the capwap protocol. + * + * Usage goes as follows. + * + * First create a FRAGMAN object: + * + * FRAGMAN * fm = fragman_create() + * + * Now you can add received fragmented packets to the fragment manager: + * + * fragman_add(fm,packet,len) + * + * if you have got all fragments fragman_add will return the the + * reasembled packet in a struct frag. if not all packets are recieved + * fragman_add will return NULL. To check if there was an error you have + * to consult errno. errno will be set if fragman_add returns NULL and there + * was another problem storing the received packet. + * + * After you have got a reassembled packet and processed it yout must + * free the memory by calling fragman_free() + */ + + +#include +#include +#include +#include +#include + + +#include "capwap.h" +#include "fragman.h" + +/* + * check if we keep already fragments belonging to the + * specified fragment id + */ +static struct frag * frag_get(struct frag * frags, int fragid) +{ + int i; + for (i=0;iFRAG_TTL) ){ + // printf("******************************new frag, %p\n",frags[i].buffer); + + frags[i].buffer=realloc(frags[i].buffer,FRAG_MAXSIZE); + if (frags[i].buffer==NULL) + return NULL; + frags[i].t=t; + frags[i].fragid=fragid; + frags[i].bytesreceived=0; + frags[i].bytesneeded=0; + return &frags[i]; + } + } + return NULL; +} + +/* +void fragman_free(FRAGMAN * frags,struct frag * f) +{ + int i; + for (i=0; ifragid==f->fragid){ + frags[i]=NULL; + break; + } + } + free(f); +} +*/ + +uint8_t * fragman_add(FRAGMAN * frags, uint8_t *packet, int hlen, int payloadlen) +{ + struct frag * f; + uint32_t val0,val1; + + /* read the transport header dword 0, + * contains hlen*/ + val0 = ntohl(*((uint32_t*)packet)); +// int hlen = (val0 >> 19) & 0x1f; + + /* read the transport header dword 1, + * contains fragid and fragoffset */ + val1 = ntohl(*(((uint32_t*)packet)+1)); + int fragid = val1>>16; + int fragoffset=(val1 >>3) & 0x1fff; + +// printf("Fragid = %i, offset = %i\n",fragid,fragoffset); + + /* determine size of payload */ +/* int payloadlen = len - hlen*4; + if (payloadlen<0){ + errno = EINVAL; + return NULL; + } +*/ + /* find / create cfragment */ + f = frag_get(frags,fragid); + if (!f){ + f = frag_new(frags,fragid); + } + if (!f){ + errno = ENOMEM; + /* out of fragmentation space */ + return NULL; + } + + errno = 0; + + int dst = fragoffset*8; + + /* copy fragment*/ + if (dst + payloadlen < FRAG_MAXSIZE) { + memcpy( f->buffer+4+dst,packet+hlen,payloadlen); + f->bytesreceived+=payloadlen; + } + + if (val0 & CWTH_FLAGS_L){ + printf("Flags L found!\n"); + f->bytesneeded=dst+payloadlen; + } + + int ti; + for (ti=0; ti<16; ti++){ + printf("%02X ",(f->buffer+4)[ti]); + + } + + + if (f->bytesneeded>0 && f->bytesneeded<=f->bytesreceived){ + uint8_t * r=f->buffer; + f->buffer=0; + printf("last bytes need %i\n",f->bytesneeded); + *((uint32_t*)(r))=f->bytesneeded; + return r; + } + +// printf("Fragman bytes needed: %i, received %i\n",f->bytesneeded,f->bytesreceived); + return NULL; +} + +FRAGMAN * fragman_create() +{ + FRAGMAN * frags; + frags = malloc(sizeof(struct frag)*FRAG_MAXIDS); + if (frags == NULL ) + return NULL; + memset (frags,0,(sizeof (struct frag ))*FRAG_MAXIDS); + return frags; +} + +void fragman_destroy(FRAGMAN * frags) +{ + int i; + for (i=0;i. + +*/ + + +#ifndef __FRAGMAN_H +#define __FRAGMAN_H + +#include +#include + +#ifndef FRAG_MAXSIZE + #define FRAG_MAXSIZE 65536+4 +#endif + +#ifndef FRAG_MAXIDS + #define FRAG_MAXIDS 10 +#endif + +#ifndef FRAG_TTL + #define FRAG_TTL 5 +#endif + + +struct frag { +// uint8_t buffer[FRAG_MAXSIZE]; + uint8_t * buffer; + int fragid; + int bytesreceived; + int bytesneeded; + struct timespec t; +}; + +typedef struct frag FRAGMAN; + + +//extern struct frag * fragman_add(struct frag * frags[], uint8_t *packet, int len); // struct cw_transport_header * th) +//extern uint8_t * fragman_add(struct frag * frags, uint8_t *packet, int len); // struct cw_transport_header * th) +extern uint8_t * fragman_add( FRAGMAN * frags, uint8_t *packet, int hlen, int payloadlen ); + +extern FRAGMAN * fragman_create(); +extern void fragman_destroy(FRAGMAN * frags); + + +//extern frag_init(struct frag ** frag[]); +extern void fragman_free(FRAGMAN * frags,struct frag * f); + + +#endif + diff --git a/src/capwap/process_discovery_request.c b/src/capwap/process_discovery_request.c new file mode 100644 index 00000000..2ab3bb78 --- /dev/null +++ b/src/capwap/process_discovery_request.c @@ -0,0 +1,48 @@ + +#include //tube +#include +#include + +#include "capwap.h" +#include "capwap_ieee80211.h" + +#include "cw_log.h" +#include "cw_util.h" + +//static int wtpinfo_readelem_discovery_req(struct wtpinfo *wtpinfo,int type,uint8_t* msgelem,int len) +static int wtpinfo_readelem_discovery_req(void * w,int type,uint8_t* msgelem,int len) +{ + struct wtpinfo * wtpinfo = (struct wtpinfo *)w; + cw_log_debug1("Process discovery req msgelem, type=%d, len=%d\n",type,len); + + if (wtpinfo_readelem_discovery_type(wtpinfo,type,msgelem,len)) + return 1; + + if (wtpinfo_readelem_wtp_board_data(wtpinfo,type,msgelem,len)) + return 1; + + if (wtpinfo_readelem_wtp_descriptor(wtpinfo,type,msgelem,len)) + return 1; + + if (wtpinfo_readelem_wtp_frame_tunnel_mode(wtpinfo,type,msgelem,len)) + return 1; + + if (wtpinfo_readelem_wtp_mac_type(wtpinfo,type,msgelem,len)) + return 1; + + if (wtpinfo_readelem_wtp_radio_info(wtpinfo,type,msgelem,len)) + return 1; + + return 0; + +} + + + +void process_discovery_request(struct wtpinfo * wtpinfo, uint8_t * msg, int len) +{ + cw_foreach_msgelem(msg,len,wtpinfo_readelem_discovery_req,wtpinfo); +} + + + diff --git a/src/capwap/process_join_request.c b/src/capwap/process_join_request.c new file mode 100644 index 00000000..246611c6 --- /dev/null +++ b/src/capwap/process_join_request.c @@ -0,0 +1,55 @@ +#include "capwap.h" +#include "capwap_ieee80211.h" + +#include //Tube +#include +#include + +#include "wtpinfo.h" +#include "cw_util.h" + + +//static int process_elem(struct wtpinfo *wtpinfo,int type,uint8_t* msgelem,int len) +static int process_elem(void *w,int type,uint8_t* msgelem,int len) +{ + struct wtpinfo * wtpinfo = (struct wtpinfo*)w; + + if (wtpinfo_readelem_location_data(wtpinfo,type,msgelem,len)) + return 1; + + if (wtpinfo_readelem_wtp_board_data(wtpinfo,type,msgelem,len)) + return 1; + + if (wtpinfo_readelem_wtp_descriptor(wtpinfo,type,msgelem,len)) + return 1; + + if (wtpinfo_readelem_wtp_name(wtpinfo,type,msgelem,len)) + return 1; + + if (wtpinfo_readelem_session_id(wtpinfo,type,msgelem,len)) + return 1; + + if (wtpinfo_readelem_wtp_frame_tunnel_mode(wtpinfo,type,msgelem,len)) + return 1; + + if (wtpinfo_readelem_wtp_mac_type(wtpinfo,type,msgelem,len)) + return 1; + + if (wtpinfo_readelem_wtp_radio_info(wtpinfo,type,msgelem,len)) + return 1; + + if (wtpinfo_readelem_ecn_support(wtpinfo,type,msgelem,len)) + return 1; + + if (wtpinfo_readelem_cw_local_ip_addr(wtpinfo,type,msgelem,len)) + return 1; + + return 0; +} + + +void process_join_request(struct wtpinfo * wtpinfo, uint8_t * msg, int len) +{ + cw_foreach_msgelem(msg,len,process_elem,(void*)wtpinfo); +} + diff --git a/src/capwap/process_msgelems.c b/src/capwap/process_msgelems.c new file mode 100644 index 00000000..688c00dd --- /dev/null +++ b/src/capwap/process_msgelems.c @@ -0,0 +1,53 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include "capwap.h" + +/* + * for each capwap message element in msgelems call the callback function + */ +int process_msgelems(uint8_t * msgelems, int len, + int (*callback)(void*,int,uint8_t*,int),void *arg ) +{ +// printf("NUNU %08X\n",msgelems); + + uint32_t val; + int type; + int elen; + int i=0; + do { + val = ntohl(*(uint32_t*)(msgelems+i)); + type=(val>>16) & 0xFFFF; + elen = val & 0xffff; + if (i+elen+4>len) { +// printf("Error AAA"); +// exit(88); + return 0; + } + + callback(arg,type,msgelems+i+4,elen); +// process_joinmsgelem(wtpman,msgelems+i+4,type,elen); +// printf("type %d, len %d\n",type,elen); + i+=elen+4; +// printf("I %d, len %d\n",i,len); + + } while (i. + +*/ + +#include "capwap.h" +/* +int process_msgelems_discovery_request(struct wtpinfo *wtpinfo,int type,uint8_t* msgelem,int len) +{ +// printf("pdiscovery msgelem: %d\n",type); + uint8_t val; + switch (type){ + case CWMSGELEM_DISCOVERY_TYPE: + if (len!=1) + return 0; + uint8_t ditype = *((uint8_t*)msgelem); +// printf("Discovery type: %d\n",ditype); + break; + case CWMSGELEM_WTP_BOARD_DATA: + if (len<4) + return 0; + wtpinfo->vendor_id = ntohl(*((uint32_t*)msgelem)); +// printf("Vendor ID %d\n",wtp_info.vendor_id); + parse_wtp_board_data(wtpinfo,msgelem+4,len-4); + + case CWMSGELEM_WTP_DESCRIPTOR: + printf("DESCRIPTOR\n"); + if (len<4) + return; + + val = ntohl(*((uint32_t*)msgelem)); + wtpinfo->max_radios=val>>24; + wtpinfo->radios_in_use=(val>>16)&0xff; + +// printf("Vendor ID %d\n",wtp_info.vendorid); +// parse_wtp_board_data(&wtp_info,msgelem+4,len-4); + +// printf("MAX RAD %d, %d\n",wtp_info.max_radios,wtp_info.radios_in_use); + + + break; + + } + return 1; +} + +*/ diff --git a/src/capwap/radioinfo.h b/src/capwap/radioinfo.h new file mode 100644 index 00000000..c705a31d --- /dev/null +++ b/src/capwap/radioinfo.h @@ -0,0 +1,32 @@ +/* + 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 . + +*/ + + +#ifndef __RADIOINFO_H +#define __RADIOINFO_H + +struct radioinfo{ + int rid; + uint32_t type; +#ifdef WITH_RMAC_SUPPORT + uint8_t * rmac; +#endif + +}; + +#endif diff --git a/src/capwap/sock.h b/src/capwap/sock.h new file mode 100644 index 00000000..e644e403 --- /dev/null +++ b/src/capwap/sock.h @@ -0,0 +1,70 @@ +/* + 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 . + +*/ + +#ifndef __SOCK_H +#define __SOCK_H + + +#include +#include +#include +#include + + +#ifdef __FreeBSD__ +#define HAVE_SIN_LEN +#define HAVE_SIN6_LEN +#endif + + + +extern int sock_create(const struct sockaddr * sa); +extern int sock_mwait(int * socklist, int socklistlen,fd_set * fset); +extern void sock_copyaddr(struct sockaddr_storage *dst, const struct sockaddr * src); +extern int sock_cmpaddr(const struct sockaddr *addr1, const struct sockaddr *addr2,int cmpport); +extern int sock_addrlen(const struct sockaddr * sa); +extern int sock_receive(int sock,void *buf, size_t len, int flags, struct sockaddr * srcaddr,socklen_t *addrlen); +extern int sock_mreceive(int * socklist, int socklistlen, void(*callback) (int * socklist,int index,struct sockaddr*,uint8_t*buf,int len)); +extern int sock_getifaddr(const char * ifname,int family, int type, struct sockaddr * sa); +extern int sock_getifhwaddr(const char *ifname, uint8_t * hwaddr, uint8_t * addrlen); +extern void sock_hwaddrtostr(const uint8_t *haddr,int len,char *dst); +extern char *sock_addrtostr(const struct sockaddr *sa, char *s, size_t maxlen); +extern int sock_strtoaddr( const char * s,struct sockaddr * saout); +extern int sock_set_recvtimeout(int sock, int seconds); + +extern int sock_getport(struct sockaddr *addr); +extern int sock_setport(struct sockaddr *addr, int port); +extern int sock_getbroadcastaddr(const struct sockaddr * addr,struct sockaddr * broadcastaddr); +extern void sock_addrinit(struct sockaddr *addr,int type); +extern int sock_set_dontfrag(int sock,int val); + +/* +enum { + SOCK_IFADDR_ADDRESS, + SOCK_IFADDR_BROADCAST, +}; +*/ + +#ifndef SOCK_RECBUFFERSIZE + #define SOCK_RECBUFFERSIZE 4096 +#endif + + + +#endif /* __SOCK_H */ + diff --git a/src/capwap/sock_addrinit.c b/src/capwap/sock_addrinit.c new file mode 100644 index 00000000..440dbea8 --- /dev/null +++ b/src/capwap/sock_addrinit.c @@ -0,0 +1,22 @@ +#include + +#include +#include +#include +#include + +void sock_addrinit(struct sockaddr *addr,int type) +{ + switch (type){ + case AF_INET: + memset(addr,0,sizeof(struct sockaddr_in)); + addr->sa_family=type; +#ifdef HAVE_SIN_LEN + addr_sa_len=sizeof(struct sockaddr_in); +#endif + return; + + } + + +} diff --git a/src/capwap/sock_addrlen.c b/src/capwap/sock_addrlen.c new file mode 100644 index 00000000..36142db8 --- /dev/null +++ b/src/capwap/sock_addrlen.c @@ -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 . + +*/ + +#include +#include +#include + +#ifdef AF_LINK +# include +#endif +#ifdef AF_PACKET +# include +#endif + +#include "sock.h" + +/** + * Determine the length of a sockaddr struct + */ +int sock_addrlen(const struct sockaddr * sa) +{ + + /* determine length */ + switch(sa->sa_family){ + case AF_INET: + return sizeof(struct sockaddr_in); +#ifdef WITH_IPV6 + case AF_INET6: + return sizeof(struct sockaddr_in6); +#endif + +#ifdef AF_PACKET + case AF_PACKET: + return sizeof(struct sockaddr_ll); +#endif + +#ifdef AF_LINK + case AF_LINK: + return sizeof(struct sockaddr_dl); +#endif + default: + return 0; + } + +} + diff --git a/src/capwap/sock_addrtostr.c b/src/capwap/sock_addrtostr.c new file mode 100644 index 00000000..5a6e8077 --- /dev/null +++ b/src/capwap/sock_addrtostr.c @@ -0,0 +1,95 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ +#include +#include + +#include +#include +#include +#include + +#ifdef AF_LINK +# include +#endif +#ifdef AF_PACKET +# include +#endif + +#include "sock.h" + +/* +void sock_hwaddrtostr(const uint8_t *haddr,int len,char *dst) +{ + int i; + for (i=0; isa_family) { + case AF_INET: + inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), s, maxlen); + port = ((struct sockaddr_in *)sa)->sin_port; + sprintf(s,"%s:%i",s,ntohs(port)); + break; + + case AF_INET6: + inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), s, maxlen); + break; +#ifdef AF_LINK + case AF_LINK: + { + struct sockaddr_dl *sl=(struct sockaddr_dl*)sa; + sock_hwaddrtostr(((uint8_t*)sl->sdl_data)+sl->sdl_nlen,sl->sdl_alen,s); + + } + break; + +#endif /* AF_LINLK */ + +#ifdef AF_PACKET + case AF_PACKET: + { + int i; + char *sp=s; + struct sockaddr_ll *sl=(struct sockaddr_ll*)sa; + for (i=0; isll_halen-1; i++){ + sprintf(sp,"%02X:",sl->sll_addr[i]); + sp+=3; + } + sprintf(sp,"%02X",sl->sll_addr[i]); + } + break; +#endif /* AF_PACKET */ + + + default: + strncpy(s, "Unknown AF", maxlen); + return NULL; + } + return s; +} diff --git a/src/capwap/sock_cmpaddr.c b/src/capwap/sock_cmpaddr.c new file mode 100644 index 00000000..136492a0 --- /dev/null +++ b/src/capwap/sock_cmpaddr.c @@ -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 . + +*/ + +#include +#include +#include + +#include "sock.h" + + +/* + * compare two sockaddrs + * returns 0 if both addrs are equal + * + */ + +int sock_cmpaddr(const struct sockaddr *addr1, const struct sockaddr *addr2,int cmpport) +{ + + uint8_t * s1, * s2; + int p1,p2; + int slen; + + if (addr1->sa_family != addr2->sa_family){ + addr1->sa_family - addr2->sa_family; + } + + switch (addr1->sa_family){ + case AF_INET: + if (cmpport){ + p1 = ((struct sockaddr_in*)addr1)->sin_port; + p2 = ((struct sockaddr_in*)addr2)->sin_port; + if (p1!=p2) + return p1-p2; + } + s1 = (uint8_t*)&(((struct sockaddr_in*)addr1)->sin_addr); + s2 = (uint8_t*)&(((struct sockaddr_in*)addr2)->sin_addr); + slen = sizeof(struct in_addr); + break; +#ifdef WITH_IPV6 + case AF_INET6: + if (cmpport){ + p1 = ((struct sockaddr_in6*)addr1)->sin6_port; + p2 = ((struct sockaddr_in6*)addr2)->sin6_port; + if (p1!=p2) + return p1-p2; + } + s1 = (uint8_t*)&(((struct sockaddr_in6*)addr1)->sin6_addr); + s2 = (uint8_t*)&(((struct sockaddr_in6*)addr2)->sin6_addr); + slen = sizeof(struct in6_addr); + break; +#endif + default: + + return -1; + } + + return memcmp(s1,s2,slen); + +} + + + diff --git a/src/capwap/sock_copyaddr.c b/src/capwap/sock_copyaddr.c new file mode 100644 index 00000000..95b0870c --- /dev/null +++ b/src/capwap/sock_copyaddr.c @@ -0,0 +1,28 @@ + +#include +#include +#include +#include + +#include "sock.h" + +void sock_copyaddr(struct sockaddr_storage *dst, const struct sockaddr * src){ + int salen; + /* determine length */ + switch(src->sa_family){ + case AF_INET: + salen = sizeof(struct sockaddr_in); + break; +#ifdef WITH_IPV6 + case AF_INET6: + salen = sizeof(struct sockaddr_in6); + break; +#endif + default: + return; + } + + memcpy(dst,src,salen); + +} + diff --git a/src/capwap/sock_create.c b/src/capwap/sock_create.c new file mode 100644 index 00000000..1a00ab14 --- /dev/null +++ b/src/capwap/sock_create.c @@ -0,0 +1,65 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include +#include +#include + + +#include "sock.h" + + +int sock_create(const struct sockaddr * sa) +{ + int sock; + int yes=1; + int salen; + /* determine length */ + switch(sa->sa_family){ + case AF_INET: + salen = sizeof(struct sockaddr_in); + break; +#ifdef WITH_IPV6 + case AF_INET6: + salen = sizeof(struct sockaddr_in6); + break; +#endif + default: + return -1; + } + + + /* bind a unicast address */ + if((sock = socket(sa->sa_family, SOCK_DGRAM, 0)) < 0) { + return -1; + } + + /* reuse address */ + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes))){ + return -1; + }; + + /* bind address */ + if ( bind(sock,sa,salen) < 0) { + return -1; + } + + return sock; +} + + diff --git a/src/capwap/sock_getbroadcastaddr.c b/src/capwap/sock_getbroadcastaddr.c new file mode 100644 index 00000000..34e45178 --- /dev/null +++ b/src/capwap/sock_getbroadcastaddr.c @@ -0,0 +1,31 @@ +#include + +#include +#include +#include + +#include "sock.h" + + + +int sock_getbroadcastaddr(const struct sockaddr * addr,struct sockaddr * broadcastaddr) +{ + struct ifaddrs *ifap,*ifa; + + if ( getifaddrs(&ifap)==-1) + return 0; + + int rc=0; + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { + + if (sock_cmpaddr(addr,ifa->ifa_addr,0)) + continue; + memcpy (broadcastaddr, ifa->ifa_broadaddr, sock_addrlen(ifa->ifa_broadaddr)); + rc=1; + break; + } + freeifaddrs(ifap); + return rc; +} + + diff --git a/src/capwap/sock_getifaddr.c b/src/capwap/sock_getifaddr.c new file mode 100644 index 00000000..07919cca --- /dev/null +++ b/src/capwap/sock_getifaddr.c @@ -0,0 +1,72 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include + +#include +#include +#include +#include + +#include "sock.h" + +int sock_getifaddr(const char * ifname,int family, int type,struct sockaddr * sa) +{ + struct ifaddrs *ifap,*ifa; + + if ( getifaddrs(&ifap)==-1) + return 0; + + int rc=0; + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { + if (strcmp(ifname,ifa->ifa_name)) + continue; + + if (ifa->ifa_addr->sa_family != family) + continue; + + if (type != 0) + if (!(ifa->ifa_flags & type)) + continue; + + switch (type){ + case 0: + memcpy (sa, ifa->ifa_addr, sock_addrlen(ifa->ifa_addr)); + rc=1; + break; + case IFF_BROADCAST: +// memcpy (sa, ifa->ifa_ifu.ifu_broadaddr, sock_addrlen(ifa->ifa_addr)); + memcpy (sa, ifa->ifa_broadaddr, sock_addrlen(ifa->ifa_addr)); + rc=1; + break; + default: + break; + + } +// rc=1; + break; + + + } + +// printf("safam: %i\n",sa->sa_family); + freeifaddrs(ifap); + return rc; +} + + diff --git a/src/capwap/sock_getifhwaddr.c b/src/capwap/sock_getifhwaddr.c new file mode 100644 index 00000000..5475aeb8 --- /dev/null +++ b/src/capwap/sock_getifhwaddr.c @@ -0,0 +1,39 @@ + +#include +#include +#include + +#ifdef AF_LINK +# include +#endif +#ifdef AF_PACKET +# include +#endif + +#include "sock.h" + + +int sock_getifhwaddr(const char *ifname, uint8_t * hwaddr, uint8_t * addrlen) +{ + struct sockaddr_storage sa; + uint8_t *src; + +#ifdef AF_PACKET + if (!sock_getifaddr(ifname,AF_PACKET,0,(struct sockaddr*)&sa)) + return 0; + *addrlen = ((struct sockaddr_ll*)&sa)->sll_halen; + src = ((struct sockaddr_ll*)&sa)->sll_addr; +#endif + +#ifdef AF_LINK + if (!sock_getifaddr(ifname,AF_LINK,0,(struct sockaddr*)&sa)) + return 0; + struct sockaddr_dl *sdl = ((struct sockaddr_dl*)&sa); + *addrlen = sdl->sdl_alen; + src = ((uint8_t*)sdl->sdl_data)+sdl->sdl_nlen; +#endif + + + memcpy(hwaddr,src,*addrlen); + return 1; +} diff --git a/src/capwap/sock_getport.c b/src/capwap/sock_getport.c new file mode 100644 index 00000000..9e71ccc7 --- /dev/null +++ b/src/capwap/sock_getport.c @@ -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 . + +*/ + +#include "sock.h" +#include +#include + +int sock_getport(struct sockaddr *addr) +{ + switch (addr->sa_family){ + case AF_INET: + return ntohs (((struct sockaddr_in*)addr)->sin_port); +#ifdef WITH_IPV6 + case AF_INET6: + return ntohs (((struct sockaddr_in6*)addr)->sin6_port); +#endif + } + return -1; +} + diff --git a/src/capwap/sock_hwaddrtostr.c b/src/capwap/sock_hwaddrtostr.c new file mode 100644 index 00000000..3592f506 --- /dev/null +++ b/src/capwap/sock_hwaddrtostr.c @@ -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 . + +*/ + +#include + +#include "sock.h" + +void sock_hwaddrtostr(const uint8_t *haddr,int len,char *dst) +{ + int i; + for (i=0; i. + +*/ + +#include +#include +#include + +#include "sock.h" + + + +int sock_mreceive(int * socklist, int socklistlen, + void(*callback) (int * socklist, int index, struct sockaddr*,uint8_t*buf,int len)) +{ + int n; + fd_set fset; + if ((n=sock_mwait(socklist,socklistlen,&fset))<0) + return -1; + + + int i; + uint8_t buffer[SOCK_RECBUFFERSIZE]; + + for( i=0; i. + +*/ +#include +#include +#include + +#include "sock.h" + +int sock_mwait(int * socklist, int socklistlen,fd_set * fset) +{ + int i; + + FD_ZERO(fset); + + int max = 0; + for (i=0; imax) + max=socklist[i]; + } + + int n; + while((n=select(max+1, fset, NULL, NULL, NULL)) < 0) { + if (errno != EINTR) + return n; + } + return n; +} + diff --git a/src/capwap/sock_receive.c b/src/capwap/sock_receive.c new file mode 100644 index 00000000..6819768c --- /dev/null +++ b/src/capwap/sock_receive.c @@ -0,0 +1,56 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include +#include +#include +#include + +#include "sock.h" + +int sock_receive(int sock,void *buf, size_t len, int flags, struct sockaddr * srcaddr,socklen_t *addrlen) +{ + + //unsigned int al; + socklen_t al; + + al = sizeof (struct sockaddr_storage); + + memset(srcaddr, 0, sizeof(struct sockaddr)); +// srcaddr->sa_port=999; + + int n; + while( (n = recvfrom(sock,(char*)buf,len,flags,srcaddr,&al)) < 0 ){ + if (errno!=EINTR) + return n ; + } +// printf("Received betes %d\n",n); +// char str[8000]; +// sock_addrtostr(srcaddr,str,1000); +// printf("RECFROM: %s\n",str); + +// struct sockaddr_in * s = (struct sockaddr_in*)srcaddr; +// s->sin_port=htons(78); +// sock_addrtostr(srcaddr,str,1000); +// printf("RECFROMset: %s\n",str); + + + +// exit(9); + return n; +} diff --git a/src/capwap/sock_set_dontfrag.c b/src/capwap/sock_set_dontfrag.c new file mode 100644 index 00000000..9a258edb --- /dev/null +++ b/src/capwap/sock_set_dontfrag.c @@ -0,0 +1,25 @@ + +#include +#include +#include + + + +int sock_set_dontfrag(int sock,int val) +{ +#if defined IP_MTU_DISCOVER && defined IP_PMTUDISC_DONT + int mtu_type; + if (val) + mtu_type = IP_PMTUDISC_DO; + else + mtu_type = IP_PMTUDISC_WANT; + + return setsockopt(sock, SOL_IP, IP_MTU_DISCOVER, &mtu_type, sizeof (mtu_type)); +#elif defined IP_DONTFRAG + + const int opt = val; + return setsockopt(sock, IPPROTO_IP, IP_DONTFRAG, &opt, sizeof (opt)); + +#endif + +} diff --git a/src/capwap/sock_set_recvtimeout.c b/src/capwap/sock_set_recvtimeout.c new file mode 100644 index 00000000..00f0c207 --- /dev/null +++ b/src/capwap/sock_set_recvtimeout.c @@ -0,0 +1,14 @@ +#include +#include +#include +#include + +#include "sock.h" + +int sock_set_recvtimeout(int sock, int seconds) +{ + struct timeval timeval; + memset(&timeval,0,sizeof(timeval)); + timeval.tv_sec=1; + return setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,&timeval,sizeof(timeval)); +} diff --git a/src/capwap/sock_setport.c b/src/capwap/sock_setport.c new file mode 100644 index 00000000..bcd38bba --- /dev/null +++ b/src/capwap/sock_setport.c @@ -0,0 +1,21 @@ +#include "sock.h" + +#include +#include + +int sock_setport(struct sockaddr *addr, int port) +{ + switch (addr->sa_family){ + case AF_INET: + ((struct sockaddr_in*)addr)->sin_port=htons(port); + break; +#ifdef WITH_IPV6 + case AF_INET6: + ((struct sockaddr_in6*)addr)->sin6_port=htonl(port); + break; +#endif + default: + return 0; + } + return 1; +} diff --git a/src/capwap/sock_strtoaddr.c b/src/capwap/sock_strtoaddr.c new file mode 100644 index 00000000..91c9d456 --- /dev/null +++ b/src/capwap/sock_strtoaddr.c @@ -0,0 +1,110 @@ +#include +#include +#include + +#include +#include +#include + +#include "sock.h" +/* + * convert a string to sockaddr struct. + * the string can contain a ipv4 or ipv6 address including a port number. + * returns 1 on success + * otherwise no success + */ +int sock_strtoaddr(const char * s,struct sockaddr * saout){ + + char *ips,*ps; + struct in_addr ia; + int port; + +#ifdef WITH_IPV6 + struct in6_addr ia6; +#endif + int rc; + + /* copy the string */ + ips = malloc(strlen(s)+1); + strcpy(ips,s); + + /* search for a collon to separate the port */ + ps = strchr(ips,':'); + if (ps != NULL){ + *ps='\0'; + ps++; + } + else + ps="0"; + + /* try to parse ip4 address */ + rc = inet_pton(AF_INET,ips,&ia); + + + if (rc==1) + { + port = atoi(ps); + if (port > 65535) + rc=0; + } + + + + if (rc==1){ + /* it's an ipv4 address */ + struct sockaddr_in * sa; + sa = (struct sockaddr_in*)saout; + memset(sa,0,sizeof(struct sockaddr_in)); +#ifdef HAVE_SIN_LEN + sa->sin_len=sizeof(struct sockaddr_in); +#endif + sa->sin_family = AF_INET; + sa->sin_addr=ia; + sa->sin_port=htons(port); + + } + +#ifdef WITH_IPV6 + if (rc==0){ + strcpy(ips,s); + + ps = strchr(ips,'.'); + if (ps != NULL){ + *ps='\0'; + ps++; + } + else + ps="0"; + + + rc = inet_pton(AF_INET6,s,&ia6); + + + if (rc==1){ + /* it's an ipv6 address */ + struct sockaddr_in6 * sa; + sa = (struct sockaddr_in6*)saout; + memset(sa,0,sizeof(struct sockaddr_in6)); + +#ifdef HAVE_SIN_LEN + sa->sin6_len=sizeof(struct sockaddr_in6); +#endif + sa->sin6_family = AF_INET6; + sa->sin6_addr=ia6; + sa->sin6_port=htons(atoi(ps)); + + + } + + } +#endif + if (rc!=1){ + if (rc!=-1) + errno=EINVAL; + } + + free (ips); + return rc; + +} + diff --git a/src/capwap/stravltree.c b/src/capwap/stravltree.c new file mode 100644 index 00000000..61febb3c --- /dev/null +++ b/src/capwap/stravltree.c @@ -0,0 +1,30 @@ +#include +#include + + +#include "stravltree.h" + + +static int cmp(const void *v1,const void*v2) +{ + return strcmp( (char*)v1,(char*)v2); +} + +static void del(void* d) +{ + free (d); + return; +} + +struct avltree * stravltree_create() +{ + return avltree_create(cmp,del); +} + +const char * stravltree_add(struct avltree * t, const char * str) +{ + char * s = strdup(str); + if (!s) + return 0; + return avltree_add(t,s); +} diff --git a/src/capwap/stravltree.h b/src/capwap/stravltree.h new file mode 100644 index 00000000..3844b53d --- /dev/null +++ b/src/capwap/stravltree.h @@ -0,0 +1,12 @@ +#ifndef __STRAVLTREE_H +#define __STRAVLTREE_H + +#include "avltree.h" + +extern struct avltree * stravltree_create(); +const char * stravltree_add(struct avltree * t, const char * str); +#define stravltree_destroy(t) avltree_destroy(t) +#define stravltree_foreach(t,f,p,d) avltree_foreach(t,f,p,d) + + +#endif diff --git a/src/capwap/wtpinfo.c b/src/capwap/wtpinfo.c new file mode 100644 index 00000000..537fdefa --- /dev/null +++ b/src/capwap/wtpinfo.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include + +#include "wtpinfo.h" +#include "capwap.h" + +#include "cw_log.h" + + +int cw_readelem_ecn_support(uint8_t *ecn_support, int type, uint8_t * msgelem, int len) +{ + if (type != CWMSGELEM_ECN_SUPPORT) + return 0; + + if (len!=1){ + cw_log_debug0("Discarding ECN_SUPPORT msgelem, wrong size, type=%d,len=%d",type,len); + return 1; + } + *ecn_support=*msgelem; + return 1; +} + +/* +int wtpinfo_readelem_ecn_support(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len) +{ + if (type != CWMSGELEM_ECN_SUPPORT) + return 0; + + if (len!=1){ + cw_log_debug0("Discarding ECN_SUPPORT msgelem, wrong size, type=%d,len=%d",type,len); + return 1; + } + wtpinfo->ecn_support=*msgelem; + return 1; + +} +*/ + +int cw_readelem_cw_local_ip_addr(struct sockaddr * local_ip, int type, uint8_t * msgelem, int len) +{ + switch (type){ + case CWMSGELEM_CAPWAP_LOCAL_IPV4_ADDRESS: + { + if (len!=4) + return -1; + struct sockaddr_in * sain = (struct sockaddr_in*)local_ip; + memset(sain,0,sizeof(struct sockaddr_in)); + #ifdef HAVE_SIN_LEN + sain->sa_len=sizeof(struct sockaddr_in); + #endif + memcpy(&sain->sin_addr,msgelem,len); + sain->sin_family=AF_INET; + return 1; + } +#ifdef WITH_IPV6 + case CWMSGELEM_CAPWAP_LOCAL_IPV6_ADDRESS: + { + if (len!=16) + return -1; + + struct sockaddr_in6 * sain = (struct sockaddr_in6*)local_ip; + memset(sain,0,sizeof(struct sockaddr_in6)); + #ifdef HAVE_SIN6_LEN + sain->sa_len=sizeof(struct sockaddr_in); + #endif + memcpy(&sain->sin6_addr,msgelem,len); + sain->sin6_family=AF_INET6; + + + return 1; + } + +#endif + } + return 0; +} + + +int wtpinfo_readelem_cw_local_ip_addr(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len) +{ + + switch (type){ + case CWMSGELEM_CAPWAP_LOCAL_IPV4_ADDRESS: + { + if (len!=4) + return -1; + struct sockaddr_in * sain = (struct sockaddr_in*)&wtpinfo->local_ip; + memset(sain,0,sizeof(struct sockaddr_in)); + #ifdef HAVE_SIN_LEN + sain->sa_len=sizeof(struct sockaddr_in); + #endif + memcpy(&sain->sin_addr,msgelem,len); + sain->sin_family=AF_INET; + return 1; + } +#ifdef WITH_IPV6 + case CWMSGELEM_CAPWAP_LOCAL_IPV6_ADDRESS: + { + if (len!=16) + return -1; + + struct sockaddr_in6 * sain = (struct sockaddr_in6*)&wtpinfo->local_ip; + memset(sain,0,sizeof(struct sockaddr_in6)); + #ifdef HAVE_SIN6_LEN + sain->sa_len=sizeof(struct sockaddr_in); + #endif + memcpy(&sain->sin6_addr,msgelem,len); + sain->sin6_family=AF_INET6; + + + return 1; + } + +#endif + } + return 0; +} + + diff --git a/src/capwap/wtpinfo.h b/src/capwap/wtpinfo.h new file mode 100644 index 00000000..7eb2fa8d --- /dev/null +++ b/src/capwap/wtpinfo.h @@ -0,0 +1,80 @@ +/* + 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 . + +*/ + +#ifndef __WTPINFO_H +#define __WTPINFO_H + +#include +#include + +#include "radioinfo.h" + +/* structure to hold info about a wtp */ +struct wtpinfo{ + uint8_t *name; + uint8_t * location; + + uint32_t vendor_id; + uint8_t* model_no; + uint8_t* serial_no; + + int max_radios; + int radios_in_use; + uint8_t frame_tunnel_mode; + + uint8_t mac_type; + uint8_t * session_id; + int session_id_len; + + struct radioinfo radioinfo[31]; + + + uint8_t * hardware_version; + uint32_t hardware_vendor_id; + uint8_t * software_version; + uint32_t software_vendor_id; + uint8_t * bootloader_version; + uint32_t bootloader_vendor_id; + + uint8_t * macaddress; + int macaddress_len; + uint8_t ecn_support; + + uint16_t max_msg_len; + uint8_t discovery_type; + + struct sockaddr_storage local_ip; + + +}; + +extern int wtpinfo_readelem_wtp_board_data(struct wtpinfo *wtpinfo, int type, uint8_t *msgelem, int len); +extern int wtpinfo_readelem_wtp_mac_type(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len); +extern int wtpinfo_readelem_wtp_radio_info(struct wtpinfo * wtpinfo,int type,uint8_t *msgelem, int len); +extern int wtpinfo_readelem_wtp_descriptor(struct wtpinfo * wtpinfo, int type, uint8_t *msgelem, int len); +extern int wtpinfo_readelem_wtp_frame_tunnel_mode(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len); +extern int wtpinfo_readelem_discovery_type(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len); +extern int wtpinfo_readelem_location_data(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len); +extern int wtpinfo_readelem_wtp_name(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len); +extern int wtpinfo_readelem_session_id(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len); +//extern int wtpinfo_readelem_ecn_support(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len); +extern int wtpinfo_readelem_cw_local_ip_addr(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len); + +#define wtpinfo_readelem_ecn_support(wtpinfo,type,msg,len) cw_readelem_ecn_support(&wtpinfo->ecn_support,type,msg,len) + +#endif diff --git a/src/capwap/wtpinfo_print.c b/src/capwap/wtpinfo_print.c new file mode 100644 index 00000000..7c421324 --- /dev/null +++ b/src/capwap/wtpinfo_print.c @@ -0,0 +1,131 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include +#include + +#include "capwap.h" +#include "sock.h" + +void radioinfo_print(struct radioinfo * radioinfo) +{ + printf(" RID %d\n",radioinfo->rid); + printf(" Modes: "); + if(radioinfo->type & CWRADIO_TYPE_B){ + printf("B"); + } + if(radioinfo->type & CWRADIO_TYPE_G){ + printf("G"); + } + + if(radioinfo->type & CWRADIO_TYPE_A){ + printf("A"); + } + + if(radioinfo->type & CWRADIO_TYPE_N){ + printf("N"); + } + + printf("\n"); + + +} + +void wtpinfo_print(struct wtpinfo * wtpinfo) +{ + char str[64]; + printf ("=== WTP Info: %p ===\n",wtpinfo); + printf (" Name:\t\t\t%s\n", (!wtpinfo->name ? (uint8_t*)"Not set" : wtpinfo->name) ); + printf (" Location:\t\t%s\n", (!wtpinfo->location ? (uint8_t*)"Not set" : wtpinfo->location) ); + + printf (" MAC Adress:\t\t"); + if (wtpinfo->macaddress){ + sock_hwaddrtostr(wtpinfo->macaddress,wtpinfo->macaddress_len,str); + printf("%s\n",str); + + } + else + printf("Not set\n"); + + sock_addrtostr((struct sockaddr*)&wtpinfo->local_ip,str,64); + printf (" Local IP:\t\t%s\n",str); + + + printf (" Vendor ID:\t\t%d\n", wtpinfo->vendor_id ); + printf (" Model No.:\t\t%s\n", (!wtpinfo->model_no ? (uint8_t*)"Not set" : wtpinfo->model_no) ); + printf (" Serial No.:\t\t%s\n", (!wtpinfo->serial_no ? (uint8_t*)"Not set" : wtpinfo->serial_no) ); + + printf (" Software Version:\t%s\n", (!wtpinfo->software_version ? (uint8_t*)"Not set" : wtpinfo->software_version) ); + + + printf (" Max Radios:\t\t%d\n",wtpinfo->max_radios); + printf (" Radios in use:\t\t%d\n",wtpinfo->radios_in_use); + + + printf (" Session ID:\t\t"); + if (wtpinfo->session_id) { + int i; + for (i=0; isession_id_len; i++) + printf("%02X",wtpinfo->session_id[i]); + } + else + printf ("Not set"); + printf("\n"); + + printf (" MAC Type:\t\t"); + switch (wtpinfo->mac_type){ + case WTP_MAC_TYPE_LOCAL: + printf("local"); + break; + case WTP_MAC_TYPE_SPLIT: + printf("split"); + break; + case WTP_MAC_TYPE_BOTH: + printf("local, split"); + break; + } + printf("\n"); + + printf (" Frame Tunnel Mode:\t"); + printf("(%08X)",wtpinfo->frame_tunnel_mode); + char * c=""; + if (wtpinfo->frame_tunnel_mode & WTP_FRAME_TUNNEL_MODE_N){ + printf ("%snative",c);c=", "; + } + + if (wtpinfo->frame_tunnel_mode & WTP_FRAME_TUNNEL_MODE_E){ + printf ("%s802.3",c);c=", "; + } + + if (wtpinfo->frame_tunnel_mode & WTP_FRAME_TUNNEL_MODE_L){ + printf ("%sLocal bridging",c);c=", "; + } + if (wtpinfo->frame_tunnel_mode == 0) + printf(" None"); + + printf("\n"); + + printf(" Radios: %d\n",wtpinfo->max_radios); + int i; + for (i=0; imax_radios; i++){ + radioinfo_print(&wtpinfo->radioinfo[i+1]); + } + + + +} diff --git a/src/capwap/wtpinfo_readelem_discovery_type.c b/src/capwap/wtpinfo_readelem_discovery_type.c new file mode 100644 index 00000000..60878930 --- /dev/null +++ b/src/capwap/wtpinfo_readelem_discovery_type.c @@ -0,0 +1,23 @@ + +#include "wtpinfo.h" +#include "capwap.h" + +#include "cw_log.h" + + +int wtpinfo_readelem_discovery_type(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len) +{ + if (type != CWMSGELEM_DISCOVERY_TYPE) + return 0; + + if (len!=1){ + cw_log_debug0("Discarding WTP_DISCOVERY_TYPE msgelem, wrong size, type=%d,len=%d",type,len); + return 1; + } + + wtpinfo->discovery_type=*msgelem; + return 1; + +} + + diff --git a/src/capwap/wtpinfo_readelem_location_data.c b/src/capwap/wtpinfo_readelem_location_data.c new file mode 100644 index 00000000..6ed54234 --- /dev/null +++ b/src/capwap/wtpinfo_readelem_location_data.c @@ -0,0 +1,19 @@ + +#include "wtpinfo.h" +#include "capwap.h" + +#include "cw_util.h" +#include "cw_log.h" + + +int wtpinfo_readelem_location_data(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len) +{ + if (type != CWMSGELEM_LOCATION_DATA) + return 0; + + cw_setstr(&wtpinfo->location,msgelem,len); + return 1; + +} + + diff --git a/src/capwap/wtpinfo_readelem_session_id.c b/src/capwap/wtpinfo_readelem_session_id.c new file mode 100644 index 00000000..5e9133d7 --- /dev/null +++ b/src/capwap/wtpinfo_readelem_session_id.c @@ -0,0 +1,22 @@ + +#include +#include + +#include "wtpinfo.h" +#include "capwap.h" + +#include "cw_util.h" +#include "cw_log.h" + +int wtpinfo_readelem_session_id(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len) +{ + if (type != CWMSGELEM_SESSION_ID) + return 0; + + wtpinfo->session_id = realloc(wtpinfo->session_id,len); + memcpy(wtpinfo->session_id,msgelem,len); + wtpinfo->session_id_len=len; + return 1; +} + + diff --git a/src/capwap/wtpinfo_readelem_wtp_board_data.c b/src/capwap/wtpinfo_readelem_wtp_board_data.c new file mode 100644 index 00000000..d86cd074 --- /dev/null +++ b/src/capwap/wtpinfo_readelem_wtp_board_data.c @@ -0,0 +1,63 @@ + +#include +#include + + +#include "wtpinfo.h" + +#include "capwap.h" + +#include "cw_util.h" +#include "cw_log.h" + + + +static void wtpinfo_readsubelems_wtp_board_data(struct wtpinfo * wtpinfo,uint8_t * msgelem,int len) +{ + int i=0; + uint32_t val; + do { + val = ntohl(*((uint32_t*)(msgelem+i))); + int subtype= (val>>16)&0xffff; + int sublen = val&0xffff; + i+=4; + if (sublen+i>len) + return; + switch(subtype){ + case CWBOARDDATA_MODELNO: + cw_setstr(&wtpinfo->model_no,msgelem+i,sublen); + break; + case CWBOARDDATA_SERIALNO: + cw_setstr(&wtpinfo->serial_no,msgelem+i,sublen); + break; + case CWBOARDDATA_MACADDRESS: + wtpinfo->macaddress=realloc(wtpinfo->macaddress,sublen); + memcpy(wtpinfo->macaddress,msgelem+i,sublen); + wtpinfo->macaddress_len=sublen; + break; + default: + break; + } + i+=sublen; + + }while(ivendor_id = ntohl(*((uint32_t*)msgelem)); + wtpinfo_readsubelems_wtp_board_data(wtpinfo,msgelem+4,len-4); + return 1; +} + + diff --git a/src/capwap/wtpinfo_readelem_wtp_descriptor.c b/src/capwap/wtpinfo_readelem_wtp_descriptor.c new file mode 100644 index 00000000..3a7cd8c7 --- /dev/null +++ b/src/capwap/wtpinfo_readelem_wtp_descriptor.c @@ -0,0 +1,62 @@ +#include "capwap.h" +#include "wtpinfo.h" + +#include "cw_util.h" + +int wtpinfo_readelem_wtp_descriptor(struct wtpinfo * wtpinfo, int type, uint8_t *msgelem, int len) +{ + if (type != CWMSGELEM_WTP_DESCRIPTOR) + return 0; + + if (len<6) + return -1; + + wtpinfo->max_radios=*msgelem; + wtpinfo->radios_in_use=*(msgelem+1); + + int ncrypt = *(msgelem+2); + + int i=ncrypt*3+3; + + do { + if (i+8>=len) + return -1; + + uint32_t vendor_id=ntohl(*((uint32_t*)(msgelem+i))); + + uint32_t val = ntohl(*((uint32_t*)(msgelem+i+4))); + int subtype= (val>>16)&0xffff; + int sublen = val&0xffff; + i+=8; + + if (sublen+i>len){ + //printf("Wrong sublen ba %d\n",sublen); + return -1; + } + + + switch(subtype){ + case CWMSGSUBELEM_WTP_DESCRIPTOR_HARDWARE_VERSION: + wtpinfo->hardware_vendor_id=vendor_id; + cw_setstr(&wtpinfo->hardware_version,msgelem+i,sublen); + break; + case CWMSGSUBELEM_WTP_DESCRIPTOR_SOFTWARE_VERSION: + wtpinfo->software_vendor_id=vendor_id; + cw_setstr(&wtpinfo->software_version,msgelem+i,sublen); + break; + case CWMSGSUBELEM_WTP_DESCRIPTOR_BOOTLOADER_VERSION: + wtpinfo->bootloader_vendor_id=vendor_id; + cw_setstr(&wtpinfo->bootloader_version,msgelem+i,sublen); + break; + default: + //printf("unknown !!!\n"); + break; + } + i+=sublen; + + }while(iframe_tunnel_mode=*msgelem; + return 1; + +} + + diff --git a/src/capwap/wtpinfo_readelem_wtp_mac_type.c b/src/capwap/wtpinfo_readelem_wtp_mac_type.c new file mode 100644 index 00000000..2c753c06 --- /dev/null +++ b/src/capwap/wtpinfo_readelem_wtp_mac_type.c @@ -0,0 +1,21 @@ + +#include "wtpinfo.h" +#include "capwap.h" + +#include "cw_log.h" + +int wtpinfo_readelem_wtp_mac_type(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len) +{ + if (type != CWMSGELEM_WTP_MAC_TYPE) + return 0; + + if (len!=1){ + cw_log_debug0("Discarding WTP_MAC_TYPE msgelem, wrong size, type=%d,len=%d",type,len); + return 1; + } + + wtpinfo->mac_type=*msgelem; + return 1; +} + + diff --git a/src/capwap/wtpinfo_readelem_wtp_name.c b/src/capwap/wtpinfo_readelem_wtp_name.c new file mode 100644 index 00000000..8d66df3d --- /dev/null +++ b/src/capwap/wtpinfo_readelem_wtp_name.c @@ -0,0 +1,23 @@ + +#include "wtpinfo.h" +#include "capwap.h" + +#include "cw_util.h" +#include "cw_log.h" + + +int wtpinfo_readelem_wtp_name(struct wtpinfo * wtpinfo, int type, uint8_t * msgelem, int len) +{ + if (type != CWMSGELEM_WTP_NAME) + return 0; + + if (len>512){ + cw_log_debug0("Truncating WTP_NAME msgelem to 512, wrong size, type=%d,len=%d",type,len); + len=512; + } + + cw_setstr(&wtpinfo->name,msgelem,len); + return 1; +} + + diff --git a/src/capwap/wtpinfo_readelem_wtp_radio_info.c b/src/capwap/wtpinfo_readelem_wtp_radio_info.c new file mode 100644 index 00000000..c315569d --- /dev/null +++ b/src/capwap/wtpinfo_readelem_wtp_radio_info.c @@ -0,0 +1,22 @@ +#include "wtpinfo.h" +#include "capwap_ieee80211.h" + +#include "cw_log.h" + + +int wtpinfo_readelem_wtp_radio_info(struct wtpinfo * wtpinfo,int type,uint8_t *msgelem, int len) +{ + if (type != CWMSGELEM_IEEE80211_WTP_RADIO_INFO) + return 0; + + if (len!=5){ + cw_log_debug0("Discarding msgelem WTP_RADIO_INFO, wrong size, len=%d\n",len); + return -1; + } + + int rid=*msgelem & 0x1f; + wtpinfo->radioinfo[rid].rid=rid; + wtpinfo->radioinfo[rid].type=*(uint32_t*)(msgelem+4); + return 1; +} + diff --git a/src/capwap/wtpinfo_set_location.c b/src/capwap/wtpinfo_set_location.c new file mode 100644 index 00000000..0a9af920 --- /dev/null +++ b/src/capwap/wtpinfo_set_location.c @@ -0,0 +1,28 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ +#include +#include + +#include "capwap.h" + +void wtpinfo_set_location(struct wtpinfo * wtpinfo, uint8_t * str, int len) +{ + wtpinfo->location = realloc(wtpinfo->location,len+1); + memcpy(wtpinfo->location,str,len); + wtpinfo->location[len]=0; +} diff --git a/src/wtp/Makefile b/src/wtp/Makefile new file mode 100644 index 00000000..eb5ba016 --- /dev/null +++ b/src/wtp/Makefile @@ -0,0 +1,77 @@ +ifndef CC +CC=gcc +endif + +CFLAGS+=-DWITH_RMAC_SUPPORT +CFLAGS+=-DWITH_IPV6 +CFLAGS+=-DWITH_CW_LOG +CFLAGS+=-DWITH_CW_LOG_DEBUG +CFLAGS+=-DWITH_DTLS + + +SYSARCH := $(shell uname -m) +ifndef ARCH + ARCH=$(SYSARCH) +endif + +X=$(shell echo $(ARCH)) + +#ifndef CFLAGS +CFLAGS += -O2 -Wall -g +#endif + +LDFLAGS += -L../../src/capwap/$(ARCH) +LDFLAGS += -L/usr/local/lib +#LDFLAGS += -lpthread +#LDFLAGS += -lrt + +LIBS+=-lcapwap +#LIBS+=-liw +LIBS+=-lssl +LIBS+=-lcrypto +LIBS+=-lpthread +LIBS+=-lrt +LIBS+=-lconfuse + + +CFLAGS += -I../src +CFLAGS += -I../src/utils +CFLAGS += -I../../src +CFLAGS += -I/usr/local/include + +OBJS += wtp_main.o +OBJS += wtp_conf.o +OBJS += discovery.o +OBJS += wtp_interface.o +OBJS += wtpdrv.o +OBJS += join.o +OBJS += run.o +OBJS += sulking.o + +ALL=wtp + +all: $(ALL) + +Q=@ +E=echo +ifeq ($(V), 1) +Q= +E=true +endif + +%.o: %.c + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + @$(E) " CC " $< + + +wtp: $(BCHECK) $(OBJS) + $(Q)$(CC) $(LDFLAGS) -o wtp $(OBJS) $(LIBS) + + @$(E) " LD " $@ + +clean: +# $(MAKE) -C ../src clean + rm -f *.o + rm -f *.d + +-include $(OBJS:%.o=%.d) diff --git a/src/wtp/discovery.c b/src/wtp/discovery.c new file mode 100644 index 00000000..0286dcef --- /dev/null +++ b/src/wtp/discovery.c @@ -0,0 +1,315 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +#include +#include +#include +#include +#include +#include + + +#include "capwap/capwap.h" +#include "capwap/cw_log.h" +#include "capwap/wtpinfo.h" +#include "capwap/acinfo.h" +#include "capwap/sock.h" +#include "capwap/cw_util.h" + +#include "wtp.h" +#include "wtp_conf.h" +#include "wtp_interface.h" + +#include + +struct discovery_info{ + ACIPLIST * aciplist; + struct conn * conn; + int response_count; +}; + +static int acprint(void *p,void*d) //,int ctr) +{ + + + ACIP * ip = (ACIP*)d; + char str[100]; + sock_addrtostr((struct sockaddr*)&ip->ip,str,100); +// printf("ACIP: %s\n",str); +// printf("CTR: %i\n",ip->wtp_count); + return 1; +} + + + + +static int msg_cb(void *priv,struct cwrmsg * cwrmsg) +{ + if (cwrmsg->type != CWMSG_DISCOVERY_RESPONSE){ + cw_log_debug0("Expected discovery response, but received %i",cwrmsg->type); + return 1; + } + + struct discovery_info * di = (struct discovery_info*)priv; + + if (di->conn->seqnum != cwrmsg->seqnum){ + cw_log_debug0("Ignoring discovery respone, seqnum=%i, expected seqnum %i",cwrmsg->seqnum,di->conn->seqnum); + return 1; + } + + struct ac_info acinfo; + memset(&acinfo,0,sizeof(acinfo)); + + acinfo.aciplist = di->aciplist; + + cwread_discovery_response(&acinfo,cwrmsg->msgelems,cwrmsg->msgelems_len); + +/* + printf("AC NAME %s\n",acinfo.ac_name); + printf("AC Software version %s\n",acinfo.software_version); + printf("AC Hardwareversion %s\n",acinfo.hardware_version); + + printf("Active wtps: %i\n",acinfo.active_wtps); + printf("Active max wtps: %i\n",acinfo.max_wtps); + + + printf("Got Discovery response\n"); + + printf("ACL COUNT: %i\n",acinfo.aciplist->count); +*/ + aciplist_foreach(acinfo.aciplist,acprint,0); + +// responses++; +// + di->response_count++; + return 1; +} + + +static void rand_sleep(int seconds) +{ + int usecs = seconds * 1000; + uint16_t rnd; + cw_rand((uint8_t*)&rnd,sizeof(rnd)); + uint16_t max = 0-1; + int r = (rnd * usecs) / max; + cw_log_debug0("Sleeping for %u milliseconds\n",r); + usleep(r*1000); +} + + +static int do_discover_conn(struct conn * conn,struct discovery_info * di) +{ + rand_sleep(conf_max_discovery_interval); + + + struct wtpinfo * wtpinfo; + wtpinfo = get_wtpinfo(); +// wtpinfo_print(wtpinfo); + + +// struct timespec tstart,tcur; + struct radioinfo ri; + memset(&ri,0,sizeof(ri)); + + +#ifdef WITH_CW_LOG_DEBUG + char str[100]; + sock_addrtostr((struct sockaddr*)&conn->addr,str,100); + cw_log_debug0("Sending discovery request to %s",str); +#endif + + int rc; + + do { + rc = cwsend_discovery_request(conn,&ri,wtpinfo); + if (rc<0){ + if (errno == EINTR) + continue; + if (errno == EMSGSIZE){ + conn->mtu-=4; + cw_log_debug2("Setting mtu to %i",conn->mtu); + continue; + } + } + break; + + }while (rc<0); + + + if (rc < 0 ) + { + char str[100]; + sock_addrtostr((struct sockaddr*)&conn->addr,str,100); + cw_log(LOG_ERR,"Error sending discovery request to %s: %s",str,strerror(errno)); + return 0; + } + + struct connlist * connlist; + connlist = connlist_create(30); + +// clock_gettime(CLOCK_REALTIME,&tstart); +// + int tstart = time(0); + int treset = 0; + do { + char buf[2048]; + int buflen=2048; + struct sockaddr_storage sa; + socklen_t fromlen=sizeof(struct sockaddr_storage); + rc = recvfrom(conn->sock,buf,buflen,0,(struct sockaddr*)&sa,&fromlen); + if (rc<0){ + if (errno==EINTR) + rc=0; + if (errno==EAGAIN) + rc=0; + if (errno==EWOULDBLOCK) + rc=0; + } + if (rc>0) { +#ifdef WITH_CW_LOG_DEBUG + char str[100]; + sock_addrtostr((struct sockaddr*)&sa,str,100); + cw_log_debug0("Received packet from %s",str); +#endif + + struct conn * rconn; + rconn = connlist_get(connlist,(struct sockaddr*)&sa); + + if (!rconn){ + rconn = conn_create(conn->sock,(struct sockaddr*)&sa,0); //msg_cb,NULL,0); + // rconn->pmsgarg=conn->pmsgarg; + rconn->mtu = conn->mtu; + rconn->seqnum=conn->seqnum; + connlist_add(connlist,rconn); + } + + conn_process_packet(rconn,(uint8_t*)buf,rc,msg_cb,di); + } + + /* reset discovery timer after we have received the first response */ + if ( di->response_count == 1 && !treset ){ + tstart=time(0); + treset=1; + } + + //clock_gettime(CLOCK_REALTIME,&tcur); +// printf("TTSub: %i %i\n",time(0)-tstart, conf_discovery_interval); + }while(time(0)-tstart < conf_discovery_interval && rc>=0 ); + + + if (rc <0){ + char str[100]; + sock_addrtostr((struct sockaddr*)&conn->addr,str,100); + cw_log(LOG_ERR,"Error sendings discovery request to %s: %s",str,strerror(errno)); + } + + connlist_destroy(connlist); + return 1; +} + + +static int discovery_count; + +ACIPLIST * do_discovery(const char *acaddr) +{ + + /* get an partially intialized connection object + * (seqnum should be set) + * */ + struct conn * conn = get_conn(); + if (!conn){ + cw_log(LOG_ERR,"Can't create conn for %s: %s",acaddr,strerror(errno)); + return 0; + } + + + /* get addr of destination */ + struct addrinfo hints; + struct addrinfo * res,*res0; + memset(&hints,0,sizeof(hints)); + + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = PF_UNSPEC; + + int rc = getaddrinfo(acaddr,conf_control_port,&hints,&res0); + if(rc){ + cw_log(LOG_ERR,"Can't connect to AC %s: %s",acaddr,gai_strerror(rc)); + return 0; + } + + struct discovery_info di; + memset (&di,0,sizeof(struct discovery_info)); + di.aciplist = aciplist_create(); + di.response_count=0; + + + for(res=res0; res; res=res->ai_next) + { + if ( discovery_count >= conf_max_discoveries){ + sulking_state(); + discovery_count=0; + cw_log_debug0("Entering discovery state"); + } + discovery_count++; + + + /* create socket */ + int sockfd; + int opt; + sockfd=socket(res->ai_family,SOCK_DGRAM,0); + if (sockfd == -1){ + cw_log(LOG_ERR,"Can't create socket for %s: %s",acaddr,strerror(errno)); + continue; + } + + opt = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt))<0){ + cw_log(LOG_ERR,"Cant set broadcast sockopt"); + } + sock_set_recvtimeout(sockfd,1); + + sock_set_dontfrag(sockfd,0); + + di.conn=conn; + + sock_copyaddr(&conn->addr,res->ai_addr); + conn->sock=sockfd; + + do_discover_conn(conn,&di); + + close(sockfd); + + if ( di.aciplist->count != 0) + break; + + } + + freeaddrinfo(res0); + + if (di.aciplist->count){ + cw_log_debug2("Discover responses received: %i\n",di.response_count); + return di.aciplist; + + } + + aciplist_destroy(di.aciplist); + return 0; +} + + diff --git a/src/wtp/join.c b/src/wtp/join.c new file mode 100644 index 00000000..84649417 --- /dev/null +++ b/src/wtp/join.c @@ -0,0 +1,127 @@ + +#include +#include +#include +#include +#include + +#include "wtp_interface.h" +#include "wtp_conf.h" + +#include "capwap/dtls.h" +#include "capwap/cw_log.h" +#include "capwap/sock.h" +#include "capwap/dtls.h" + + +#define acinfo_log acinfo_log_ + +void acinfo_log_(int level,const struct ac_info *acinfo,const char * xstr) +{ + char str[8192]; + acinfo_print(str,acinfo); + cw_log_debug(level,"%s\n%s",xstr,str); + return; +} + + + + +int join_state(struct conn * conn) +{ + struct wtpinfo * wtpinfo = get_wtpinfo(); + + struct radioinfo ri; + memset(&ri,0,sizeof(ri)); + int rc; + +#ifdef WITH_CW_LOG_DEBUG + char str[64]; + sock_addrtostr(&conn->addr,str,64); + cw_log_debug0("Sending join request to %s",str); +#endif + printf("Seqnum before = %i\n",conn->seqnum); + rc = cwsend_join_request(conn,&ri,wtpinfo); + printf("Seqnum after = %i\n",conn->seqnum); + + struct cwrmsg * cwrmsg = conn_get_message(conn); + + cw_log_debug0("Receiveid message %i",cwrmsg->seqnum); + + if (cwrmsg->type != CWMSG_JOIN_RESPONSE || cwrmsg->seqnum != conn->seqnum){ + printf("Wrong message\n"); + } + + struct ac_info acinfo; + memset(&acinfo,0,sizeof(acinfo)); + + cwread_join_response(&acinfo,cwrmsg->msgelems,cwrmsg->msgelems_len); + acinfo_log(0,&acinfo,"Connectet to the following AC"); +} + + + +int join(struct sockaddr *sa) +{ + int sockfd; + int rc; + + sockfd = socket(AF_INET,SOCK_DGRAM,0); + if (sockfd==-1){ + cw_log(LOG_ERR,"Can't create socket: %s\n",strerror(errno)); + return -1; + } + + sock_set_recvtimeout(sockfd,1); + + rc = connect(sockfd,(struct sockaddr*)sa,sock_addrlen((struct sockaddr*)sa)); + if (rc<0){ + char str[100]; + sock_addrtostr(sa,str,100); + cw_log(LOG_ERR,"Can't connect to %s: %s\n",str,strerror(errno)); + close(sockfd); + return -1; + } + + struct conn * conn = get_conn(); + conn->sock=sockfd; + sock_copyaddr(&conn->addr,sa); + + +#ifdef WITH_DTLS + #ifdef WITH_CW_LOG_DEBUG + { + char str[100]; + sock_addrtostr(sa,str,100); + cw_log_debug0("Establishing DTLS connection to %s",str); + } + #endif + + conn->dtls_psk=conf_dtls_psk; + conn->dtls_psk_len=strlen(conn->dtls_psk); + conn->dtls_cipher=conf_dtls_cipher; + + rc = dtls_connect(conn); + if (rc!=1){ + dtls_shutdown(conn); + char str[100]; + sock_addrtostr(sa,str,100); + cw_log(LOG_ERR,"Cant establish DTLS connection to %s",str); + close(sockfd); + return 0; + } + +#endif + + #ifdef WITH_CW_LOG_DEBUG + { + char str[100]; + sock_addrtostr(sa,str,100); + cw_log_debug0("DTLS connection to %s established",str); + } + #endif + + join_state(conn); + + return 1; +} diff --git a/src/wtp/run.c b/src/wtp/run.c new file mode 100644 index 00000000..27c36e8f --- /dev/null +++ b/src/wtp/run.c @@ -0,0 +1,98 @@ +#include +#include + +#include "capwap/capwap.h" +#include "capwap/conn.h" +#include "capwap/radioinfo.h" +#include "capwap/cw_log.h" +#include "capwap/dtls.h" + + +#include "wtp_conf.h" + +static int echo_interval_timer; + +struct cwrmsg * get_response(struct conn * conn, int type,int seqnum) +{ + struct cwrmsg * cwrmsg; + int i; + for(i=0; itype==type && cwrmsg->seqnum==seqnum) + return cwrmsg; + printf("another message was detected %i %i\n",cwrmsg->type,cwrmsg->seqnum); + } + return 0; + +} + + + +struct cwrmsg * send_request(struct conn * conn,struct cwmsg *cwmsg) +{ + int i; + for (i=0; i0){ + cw_log_debug1("Retransmitting request, type=%i,seqnum=%i",cwmsg->type,cwmsg->seqnum); + } +#endif + + int rc = conn_send_cwmsg(conn,cwmsg); + if (rc<0){ + cw_log_debug1("Error sending request, type=%i, seqnum %i, %s",cwmsg->type,cwmsg->seqnum,strerror(errno)); + return 0; + } + struct cwrmsg * r = get_response(conn,cwmsg->type+1,cwmsg->seqnum); + if (r) + return r; + + } + return 0; +} + + + + +int run(struct conn * conn) +{ + struct radioinfo radioinfo; + memset(&radioinfo,0,sizeof(radioinfo)); + + echo_interval_timer=time(NULL); + while (1){ + if (time(NULL)-echo_interval_timer >= conf_echo_interval) + { + struct cwmsg cwmsg; + uint8_t buffer[CWMSG_MAX_SIZE]; + + // cwsend_echo_request(conn,&radioinfo); + + cw_log_debug1("Sending echo request"); + cwmsg_init_echo_request(&cwmsg,buffer,conn,&radioinfo); + struct cwrmsg * rc = send_request(conn,&cwmsg); + +// printf("conn->seqnum %i\n",conn->seqnum); +// struct cwrmsg * rc = get_response(conn,CWMSG_ECHO_RESPONSE,conn->seqnum); + if (rc==0){ + + dtls_shutdown(conn); + cw_log_debug1("Connection lost, no echo response"); + return 0; + } + echo_interval_timer=time(NULL); + } + sleep(1); + + } + exit(0); +} + + + diff --git a/src/wtp/sulking.c b/src/wtp/sulking.c new file mode 100644 index 00000000..b62533f6 --- /dev/null +++ b/src/wtp/sulking.c @@ -0,0 +1,15 @@ +#include + +#include "capwap/cw_log.h" + +#include "wtp.h" +#include "wtp_conf.h" + +int sulking_state() +{ + cw_log_debug0("Entering Sulking state"); + cw_log_debug0("Sleeping for %i seconds",conf_silent_interval); + sleep(conf_silent_interval); + return 1; +} + diff --git a/src/wtp/wtp.defaul.conf b/src/wtp/wtp.defaul.conf new file mode 100644 index 00000000..ede74619 --- /dev/null +++ b/src/wtp/wtp.defaul.conf @@ -0,0 +1,81 @@ +# + +dtls_psk = Tube +wtp_name = "tabbe" + + +#primary_if = eth0 + +preferred_ac = 192.168.0.15 + + +# ac_list +# list of ACs where to send discovery requests +# +# default: +# ac_list = + + +# conf_control_port +# +# default: +# control_port = 5246 + +# max_discovery_interval +# before sending a discovery request the wtp +# will sleep for a randomly selected time not +# greater than max_discovery_interval +# +# deault: +# max_discovery_interval = 20 +max_discovery_interval = 2 + + +# discovery_interval +# the number of seconds the wtp will wait after +# receiving a discovery response to get eventually +# discovery response messages from other ACs. +# +# default: +# discovery_interval = 5 +discovery_interval = 1 + +# max_discoveries +# the number of discovery request sent by the wtp +# before the wtp enters suking state +# +# default: +# max_discoveries = 10 +max_discoveries = 3 + + +# silent_interval +# number of seconds to sleep in sulking state +# +# default: +# silent_interval = 30 + +silent_interval = 4 + +# dtls_cipher +# supported ciphers +# +# default: +# dtls_cipher = "PSK-AES128-CBC-SHA" + +# debug_level +# debug level +# +# default: +# debug_level = + +# max_retransmit +# maximum number of retransmissions for capwap packets +# default: +# max_retransmit = 5 + +# echo_interval +# default: +# echo_interval = 30 + + diff --git a/src/wtp/wtp.h b/src/wtp/wtp.h new file mode 100644 index 00000000..24167754 --- /dev/null +++ b/src/wtp/wtp.h @@ -0,0 +1,7 @@ +#ifndef __WTP_H +#define __WTP_H + +extern int sulking_state(); +extern int join(); + +#endif diff --git a/src/wtp/wtp_conf.c b/src/wtp/wtp_conf.c new file mode 100644 index 00000000..05b3c7b6 --- /dev/null +++ b/src/wtp/wtp_conf.c @@ -0,0 +1,254 @@ + +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include "capwap/capwap.h" +#include "capwap/cw_log.h" +#include "wtp_conf.h" + +char * conf_primary_if=0; +char * conf_wtpname=0; +char * conf_dtls_psk=0; +char * conf_preferred_ac=0; +char * conf_dtls_cipher=0; + + +struct sockaddr_storage * conf_preferred_ac_sa=0; + + +char ** conf_ac_list; +int conf_ac_list_len; +char * conf_control_port=0; +uint8_t conf_macaddress[12]; +uint8_t conf_macaddress_len=0; + +long conf_max_discovery_interval=CONF_DEFAULT_MAX_DISCOVERY_INTERVAL; +long conf_discovery_interval=CONF_DEFAULT_DISCOVERY_INTERVAL; +long conf_silent_interval=CONF_DEFAULT_SILENT_INTERVAL; +long conf_max_discoveries=CONF_DEFAULT_MAX_DISCOVERIES; +long conf_echo_interval=CONF_DEFAULT_ECHO_INTERVAL; +long conf_max_retransmit=CONF_DEFAULT_MAX_RETRANSMIT; +long conf_retransmit_interval=CONF_DEFAULT_RETRANSMIT_INTERVAL; + +long conf_debug_level=CONF_DEFAULT_DEBUG_LEVEL; + + +int wtpconf_init() +{ + + + if (conf_preferred_ac){ + conf_preferred_ac_sa=malloc(sizeof(struct sockaddr_storage)); + if (sock_strtoaddr(conf_preferred_ac,conf_preferred_ac_sa)!=1) + { + cw_log(LOG_ERR,"Preferred AC, invalid address: %s",conf_preferred_ac); + free(conf_preferred_ac_sa); + conf_preferred_ac_sa=0; + } + else{ + if (sock_getport(conf_preferred_ac_sa)==0){ + sock_setport(conf_preferred_ac_sa,conf_control_port); + } + } + if (conf_preferred_ac_sa!=0){ + char str[100]; + sock_addrtostr(conf_preferred_ac_sa,str,100); + cw_log(LOG_INFO,"Preferred AC: %s\n",str); + } + } + +} + +#include + +char * get_prim(int family) +{ + struct ifaddrs *ifap,*ifa; + char * r = 0; + + getifaddrs(&ifap); + + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_flags & IFF_LOOPBACK){ + continue; + } + + if (ifa->ifa_addr->sa_family != family) + continue; + + r = malloc(strlen(ifa->ifa_name)+1); + if (r) + strcpy(r,ifa->ifa_name); + break; + + } + freeifaddrs(ifap); + return r; +} + + +wtpconf_primary_if() +{ + if (!conf_primary_if){ + +#ifdef WITH_IPV6 + conf_primary_if = get_prim(AF_INET6); + if (!conf_primary_if) + conf_primary_if = get_prim(AF_INET); +#else + conf_primary_if = get_prim(AF_INET); +#endif + if (!conf_primary_if){ + cw_log(LOG_ERR,"Fatal: Unable to detect primary interface"); + return 0; + } + + } + if (!sock_getifhwaddr(conf_primary_if,conf_macaddress,&conf_macaddress_len)){ + cw_log(LOG_ERR,"Fatal: Unable to detect link layer address for %s\n",conf_primary_if); + return 0; + }; + +#ifdef WITH_CW_LOG_DEBUG + char str[128]; + sock_hwaddrtostr(conf_macaddress,conf_macaddress_len,str); + cw_log_debug0("Using primary interface: %s",conf_primary_if); + cw_log_debug0("Using primary mac address: %s",str); +#endif + return 1; +} + + + +char * default_ac_list[] = { + "255.255.255.255", + "224.0.1.140", +}; + +wtpconf_ac_list() +{ + if (conf_ac_list) + return 1; + + int i; + int len=0; + int bcrc; + struct sockaddr_storage bcaddr; + + bcrc = sock_getifaddr(conf_primary_if,AF_INET,IFF_BROADCAST,&bcaddr); + if (bcrc) + len++; + + int deflen = sizeof(default_ac_list)/sizeof(char*); + + len += deflen; + conf_ac_list = malloc(len*sizeof(char*)); + if (!conf_ac_list) + return 0; + + for (i=0; i0) + { + conf_ac_list=malloc(sizeof(char*)*n); + if (!conf_ac_list) + goto errX; + + conf_ac_list_len=0; + for (i=0; i + +#include "capwap/capwap.h" + +extern int read_config(const char * filename); +extern char * conf_wtpname; +extern char * conf_dtls_psk; +extern struct sockaddr_storage * conf_preffered_ac_sa; +extern char * conf_primary_if; + +extern char ** conf_ac_list; + +extern int conf_ac_list_len; +extern char * conf_control_port; + +extern uint8_t conf_macaddress[12]; +extern uint8_t conf_macaddress_len; + + + +#ifndef CONF_DEFAULT_MAX_DISCOVERY_INTERVAL + #define CONF_DEFAULT_MAX_DISCOVERY_INTERVAL CAPWAP_MAX_DISCOVERY_INTERVAL +#endif + +#ifndef CONF_DEFAULT_SILENT_INTERVAL + #define CONF_DEFAULT_SILENT_INTERVAL CAPWAP_SILENT_INTERVAL +#endif + +#ifndef CONF_DEFAULT_DISCOVERY_INTERVAL + #define CONF_DEFAULT_DISCOVERY_INTERVAL CAPWAP_DISCOVERY_INTERVAL +#endif + +#ifndef CONF_DEFAULT_MAX_DISCOVERIES + #define CONF_DEFAULT_MAX_DISCOVERIES CAPWAP_MAX_DISCOVERIES +#endif + +#ifndef CONF_DEFAULT_DTLS_CIPHER + #define CONF_DEFAULT_DTLS_CIPHER CAPWAP_CIPHER +#endif + +#define CONF_DEFAULT_ECHO_INTERVAL CAPWAP_ECHO_INTERVAL +#define CONF_DEFAULT_MAX_RETRANSMIT CAPWAP_MAX_RETRANSMIT +#define CONF_DEFAULT_RETRANSMIT_INTERVAL CAPWAP_RETRANSMIT_INTERVAL + +#define CONF_DEFAULT_DEBUG_LEVEL -1 + + +extern long conf_max_discovery_interval; +extern long conf_discovery_interval; +extern long conf_silent_interval; +extern long conf_max_discoveries; +extern char * conf_dtls_cipher; +extern long conf_echo_interval; +extern long conf_max_retransmit; +extern long conf_retransmit_interval; + +extern long conf_debug_level; + +#endif diff --git a/src/wtp/wtp_interface.c b/src/wtp/wtp_interface.c new file mode 100644 index 00000000..27d2e52f --- /dev/null +++ b/src/wtp/wtp_interface.c @@ -0,0 +1,80 @@ + +#include + + +#include "capwap/wtpinfo.h" +#include "capwap/acinfo.h" +#include "capwap/conn.h" + +#include "wtp_conf.h" +#include "wtp_interface.h" + + +struct wtpinfo * get_wtpinfo() +{ + struct wtpinfo * wtpinfo; + wtpinfo=malloc(sizeof(struct wtpinfo)); + memset(wtpinfo,0,sizeof(struct wtpinfo)); + + wtpinfo->name = (uint8_t*)"wtp"; + wtpinfo->location = (uint8_t*)"Unknown"; + + wtpinfo->max_radios=wtpdrv_get_num_radios(); +/* int i; + for (i=0; iserial_no="123456789"; + wtpinfo->vendor_id=909090; + + wtpinfo->model_no="WNDR 3700"; + + wtpinfo->bootloader_version="1.0"; + wtpinfo->bootloader_vendor_id=12345; + + wtpinfo->hardware_version="2.5"; + wtpinfo->hardware_vendor_id=909090; + + wtpinfo->software_version="2.0"; + wtpinfo->software_vendor_id=109090; + + wtpinfo->macaddress=conf_macaddress; + wtpinfo->macaddress_len=conf_macaddress_len; + + wtpinfo->mac_type=1; + + + wtpinfo->session_id = malloc(8); + wtpinfo->session_id_len = cw_rand(wtpinfo->session_id,8); + + + wtpinfo->frame_tunnel_mode=0; + return wtpinfo; +} + +void destroy_wtpinfo(struct wtpinfo* wtpinfo) +{ + +} + + +ACIPLIST * order_aciplist(ACIPLIST *aciplistin) +{ +// ACIPLIST * aciplist = aciplist_create(); + +// aciplist_foreach(aciplistin); + + return aciplistin; +} + + +static struct conn * conn=0; +struct conn * get_conn() +{ + if (!conn){ + conn = conn_create(-1,0,0); + } + return conn; +} diff --git a/src/wtp/wtp_interface.h b/src/wtp/wtp_interface.h new file mode 100644 index 00000000..cf50a297 --- /dev/null +++ b/src/wtp/wtp_interface.h @@ -0,0 +1,9 @@ +#ifndef __WTP_INTERFACE_H +#define __WTP_INTERFACE_H + +#include "capwap/wtpinfo.h" +extern struct wtpinfo * get_wtpinfo(); +extern struct conn * get_conn(); + +#endif + diff --git a/src/wtp/wtp_main.c b/src/wtp/wtp_main.c new file mode 100644 index 00000000..4213dc45 --- /dev/null +++ b/src/wtp/wtp_main.c @@ -0,0 +1,130 @@ + +#include +#include +#include + +//#include + +#include "capwap/sock.h" +#include "capwap/conn.h" +#include "capwap/dtls.h" +#include "capwap/avltree.h" +#include "capwap/cw_log.h" +#include "capwap/capwap.h" +#include "capwap/cw_util.h" +#include "capwap/wtpinfo.h" + +#include "wtp.h" +#include "wtp_conf.h" + + + +struct wtpinfo wtpinfo; + +//int conf_rids[2]; +//int conf_rids_len[2]; + +//int responses = 0; + +struct avltree * aclist =0; + + +extern struct wpa_driver_ops *wpa_drivers[]; + + +#include +#include +#include +#include + +//struct sockaddr conf_preferred_ac; + + + +static void * drv_priv[2]; +static void * drv_glob[2]; + +const char * interfaces[]={ + "wlan0", + "wlan1-1" +}; + +/*static int drv_init() +{ + return 1; +} +*/ + +int main() +{ + wtp_main(); +} + + +#include + + + +//#include + +int do_connect(void *priv,void *data) +{ + ACIP * ip = (ACIP*)data; +// char str[100]; +// sock_addrtostr((struct sockaddr*)&ip->ip,str,100); + + sock_setport(&ip->ip,atoi(conf_control_port)); +// printf("Would connect to %s\n",str); + + int rc =join(&ip->ip); + if (!rc) + return 1; + + run (get_conn()); + return 0; +} + +int wtp_main(const char *ad) +{ + if (!read_config("wtp.conf")){ + return 1; + } + cw_log_debug_level=conf_debug_level; + +#ifdef WITH_DTLS + dtls_init(); +#endif + + //drv_init(); + + + while (1){ + ACIPLIST * aciplist=0; + int i; + + cw_log_debug0("Entering discovery state"); + + do { + for (i=0; irid=rid; + + hwm = drv->get_hw_feature_data(drv_priv[rid-1],&nummodes,&fl); + + int i; + for (i=0; itype|=CWRADIO_TYPE_B; + printf("Mode B\n"); + break; + case HOSTAPD_MODE_IEEE80211G: + radioinfo->type|=CWRADIO_TYPE_G; + printf("Mode G\n"); + break; + case HOSTAPD_MODE_IEEE80211A: + radioinfo->type|=CWRADIO_TYPE_A; + printf("Mode A\n"); + break; + case NUM_HOSTAPD_MODES: + printf("NIMA AP MODES\n"); + break; + + } + if (hwm[i].ht_capab) + radioinfo->type|=CWRADIO_TYPE_N; + + printf ("ht_capab: %d\n",hwm[i].ht_capab); + printf ("flags: %d\n",hwm[i].flags); + printf("\n"); + } + + + +////////////// printf("hem %p\n",hwm); + +// drv + + + +} + +*/ + + diff --git a/src/wtp/wtpdrv.h b/src/wtp/wtpdrv.h new file mode 100644 index 00000000..1637bb25 --- /dev/null +++ b/src/wtp/wtpdrv.h @@ -0,0 +1,4 @@ + + +int wtpdrv_get_num_radios(); +