Initial commit
FossilOrigin-Name: c53d95729c009f8f80a7d63847cef7668ff73f8af0523ab65f7734696f85399c
This commit is contained in:
parent
3234327f71
commit
2bae9358d7
63
src/ac/Makefile
Normal file
63
src/ac/Makefile
Normal file
@ -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)
|
27
src/ac/ac.default.conf
Normal file
27
src/ac/ac.default.conf
Normal file
@ -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
|
102
src/ac/ac_interface.c
Normal file
102
src/ac/ac_interface.c
Normal file
@ -0,0 +1,102 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#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; i<socklist_len;i++){
|
||||
|
||||
if (socklist[i].type != SOCKLIST_UNICAST_SOCKET)
|
||||
break;
|
||||
|
||||
struct sockaddr_storage sa;
|
||||
unsigned int salen=sizeof(sa);
|
||||
if ( getsockname(socklist[i].sockfd,(struct sockaddr*)&sa,&salen)<0)
|
||||
continue;
|
||||
|
||||
ACIP * acip;
|
||||
acip = malloc(sizeof(ACIP));
|
||||
if (!acip)
|
||||
continue;
|
||||
|
||||
sock_copyaddr(&acip->ip,(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;
|
||||
}
|
||||
|
219
src/ac/ac_main.c
Normal file
219
src/ac/ac_main.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#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; i<conf_listen_addrs_len; i++){
|
||||
socklist_add_unicast(conf_listen_addrs[i],conf_control_port);
|
||||
}
|
||||
|
||||
if (socklist_len==0){
|
||||
cw_log(LOG_ERR,"Fatal error: Could not setup any listen socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* create multicast sockets */
|
||||
for (i=0; i<conf_mcast_groups_len;i++){
|
||||
socklist_add_multicast(conf_mcast_groups[i],conf_control_port);
|
||||
}
|
||||
|
||||
/* broadcast sockety ipv4 only */
|
||||
for (i=0; i<conf_bcast_addrs_len;i++){
|
||||
socklist_add_broadcast(conf_bcast_addrs[i],conf_control_port);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
while(1){
|
||||
|
||||
/* prepare fdset */
|
||||
fd_set fset;
|
||||
int max = 0;
|
||||
FD_ZERO(&fset);
|
||||
for (i=0; i<socklist_len; i++){
|
||||
FD_SET(socklist[i].sockfd,&fset);
|
||||
if (socklist[i].sockfd>max)
|
||||
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<socklist_len; i++){
|
||||
|
||||
if (!FD_ISSET(socklist[i].sockfd,&fset))
|
||||
continue;
|
||||
|
||||
struct sockaddr_storage srcaddr;
|
||||
socklen_t sockaddrlen;
|
||||
|
||||
memset(&srcaddr,0,sizeof(struct sockaddr_storage));
|
||||
sockaddrlen = sizeof(struct sockaddr_storage);
|
||||
|
||||
uint8_t buffer[4096];
|
||||
int len = sock_receive(socklist[i].sockfd,
|
||||
buffer, sizeof(buffer),
|
||||
0,
|
||||
(struct sockaddr*)&srcaddr, &sockaddrlen);
|
||||
|
||||
process_ctrl_packet(i, (struct sockaddr*)&srcaddr,buffer,len);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* close and free all sockts */
|
||||
for(i=0; i<socklist_len; i++){
|
||||
// close(socklist[i]);
|
||||
}
|
||||
free(socklist);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void process_ctrl_packet(int index,struct sockaddr * addr, uint8_t * buffer, int len)
|
||||
{
|
||||
int sock = socklist[index].reply_sockfd;
|
||||
|
||||
#ifdef WITH_CW_LOG_DEBUG
|
||||
char str[100];
|
||||
sock_addrtostr(addr,str,100);
|
||||
cw_log_debug0("Received packet from %s, len = %i, via %s\n",str,len,
|
||||
socklist[index].type==SOCKLIST_UNICAST_SOCKET ? "unicast":"bcast/mcast");
|
||||
cw_log_debug2_dump(buffer,len,"Packet data for packet, recevied from %s",str);
|
||||
#endif
|
||||
|
||||
/* first of all check preamble */
|
||||
int preamble = CWTH_GET_PREAMBLE(buffer);
|
||||
|
||||
#ifdef WITH_DTLS
|
||||
if (preamble != CAPWAP_PACKET_PREAMBLE && preamble != CAPWAP_DTLS_PACKET_PREAMBLE){
|
||||
#else
|
||||
if (preamble != CAPWAP_PACKET_PREAMBLE ){
|
||||
#endif
|
||||
cw_log_debug0("Discarding packet, wrong preamble, preamble = 0x%01X",preamble);
|
||||
return;
|
||||
}
|
||||
|
||||
wtplist_lock();
|
||||
struct wtpman * wtpman = wtplist_get(addr);
|
||||
if (!wtpman){
|
||||
|
||||
wtpman = wtpman_create(index,addr);
|
||||
|
||||
if (!wtpman ){
|
||||
cw_log(LOG_ERR,"Error creating wtpman: %s",strerror(errno));
|
||||
wtplist_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!wtplist_add(wtpman)){
|
||||
cw_log(LOG_ERR,"Error adding wtpman: Too many wtp connections");
|
||||
wtpman_destroy(wtpman);
|
||||
wtplist_unlock();
|
||||
return;
|
||||
};
|
||||
|
||||
wtpman_start(wtpman,preamble & 0xf);
|
||||
}
|
||||
|
||||
wtpman_addpacket(wtpman,buffer,len);
|
||||
wtplist_unlock();
|
||||
}
|
||||
|
||||
|
||||
|
2
src/ac/actube.h
Normal file
2
src/ac/actube.h
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
#define AC_MAX_LISTEN_SOCKETS 32
|
493
src/ac/conf.c
Normal file
493
src/ac/conf.c
Normal file
@ -0,0 +1,493 @@
|
||||
/*
|
||||
This file is part of actube.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <confuse.h>
|
||||
|
||||
#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 <ifaddrs.h>
|
||||
|
||||
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<n4; i++){
|
||||
uint8_t *g = (uint8_t*)conf_default_mcast_groups_ipv4[i];
|
||||
conf_mcast_groups[ctr]=(char*)cw_setstr((uint8_t**)&conf_mcast_groups[ctr],g,strlen((char*)g));
|
||||
if (conf_mcast_groups[ctr])
|
||||
ctr++;
|
||||
}
|
||||
|
||||
for(i=0; i<n6; i++){
|
||||
uint8_t *g = (uint8_t*)conf_default_mcast_groups_ipv6[i];
|
||||
conf_mcast_groups[ctr]=(char*)cw_setstr((uint8_t**)&conf_mcast_groups[ctr],g,strlen((char*)g));
|
||||
if (conf_mcast_groups[ctr])
|
||||
ctr++;
|
||||
}
|
||||
|
||||
|
||||
conf_mcast_groups_len=n;
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static int conf_read_strings( cfg_t * cfg, char * name, char ***dst,int *len)
|
||||
{
|
||||
|
||||
int n,i;
|
||||
n = cfg_size(cfg, name);
|
||||
*len=n;
|
||||
if (n==0)
|
||||
return 1;
|
||||
|
||||
*dst = malloc(sizeof(char*)*n);
|
||||
if (!*dst)
|
||||
return 0;
|
||||
|
||||
for (i=0; i<n; i++) {
|
||||
char * str = cfg_getnstr(cfg,name,i);
|
||||
if (!((*dst)[i]=malloc(strlen(str)+1))) {
|
||||
*len=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy((*dst)[i],str);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int read_config(const char * filename){
|
||||
int i,n;
|
||||
|
||||
cfg_opt_t opts[] = {
|
||||
CFG_STR_LIST("listen", "{}", CFGF_NONE),
|
||||
CFG_STR_LIST("mcast_groups", "{}", CFGF_NONE),
|
||||
CFG_STR_LIST("bcast_addrs", "{}", CFGF_NONE),
|
||||
CFG_STR_LIST("ac_ips","{}",CFGF_NONE),
|
||||
CFG_SIMPLE_STR("control_port",&conf_control_port),
|
||||
CFG_SIMPLE_INT("max_wtps",&conf_max_wtps),
|
||||
CFG_SIMPLE_INT("debug_level",&conf_debug_level),
|
||||
CFG_SIMPLE_INT("vendor_id",&conf_vendor_id),
|
||||
CFG_SIMPLE_STR("ac_name",&conf_acname),
|
||||
CFG_SIMPLE_STR("ssl_cert",&conf_sslcertfilename),
|
||||
CFG_SIMPLE_STR("ssl_key",&conf_sslkeyfilename),
|
||||
CFG_SIMPLE_STR("dtls_psk",&conf_dtls_psk),
|
||||
// CFG_SIMPLE_BOOL("ignore_wtp_source_port",&conf_ignore_wtp_source_port),
|
||||
CFG_SIMPLE_BOOL("ipv4",&conf_ipv4),
|
||||
CFG_SIMPLE_BOOL("ipv6",&conf_ipv6),
|
||||
|
||||
|
||||
CFG_SIMPLE_STR("db_file",conf_db_file),
|
||||
|
||||
CFG_END()
|
||||
};
|
||||
cfg_t *cfg;
|
||||
cfg = cfg_init(opts, 0);
|
||||
|
||||
cfg_parse(cfg, filename);
|
||||
|
||||
/* read the listen addresses */
|
||||
conf_read_strings(cfg,"listen",&conf_listen_addrs,&conf_listen_addrs_len);
|
||||
|
||||
/* read multi cast groups */
|
||||
conf_read_strings(cfg,"mcast_groups",&conf_mcast_groups,&conf_mcast_groups_len);
|
||||
|
||||
/* read ipv4 broadcast addresses */
|
||||
conf_read_strings(cfg,"bcast_addrs",&conf_bcast_addrs,&conf_bcast_addrs_len);
|
||||
|
||||
|
||||
/*
|
||||
n = cfg_size(cfg, "listen");
|
||||
if (! (conf_salist = malloc(sizeof (struct sockaddr_storage)*n)) )
|
||||
return 0;
|
||||
|
||||
if (! (conf_listen_addrs=malloc(sizeof(char *)*n)))
|
||||
return 0;
|
||||
|
||||
memset(conf_listen_addrs,0,sizeof(char*)*n);
|
||||
|
||||
conf_salist_len=n;
|
||||
for (i=0; i<n; i++) {
|
||||
char * str = cfg_getnstr(cfg,"listen",i);
|
||||
if (!(conf_listen_addrs[i]=malloc(strlen(str)+1)))
|
||||
return 0;
|
||||
|
||||
strcpy(conf_listen_addrs[i],str);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* read ac_ips */
|
||||
n = cfg_size(cfg, "ac_ips");
|
||||
if (! (conf_ac_ips = malloc(sizeof (struct sockaddr)*n)) )
|
||||
return 0;
|
||||
|
||||
conf_ac_ips_len=n;
|
||||
for (i=0; i<n; i++) {
|
||||
struct sockaddr sa;
|
||||
char * str = cfg_getnstr(cfg,"ac_ips",i);
|
||||
if (sock_strtoaddr ( cfg_getnstr(cfg, "ac_ips", i),&sa))
|
||||
conf_ac_ips[i]=sa;
|
||||
else{
|
||||
perror(str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cfg_free(cfg);
|
||||
|
||||
if (!init_acname() )
|
||||
return 0;
|
||||
|
||||
if (!init_version())
|
||||
return 0;
|
||||
|
||||
if (!init_vendor_id())
|
||||
return 0;
|
||||
|
||||
if (!init_dtls())
|
||||
return 0;
|
||||
|
||||
|
||||
if (!init_control_port())
|
||||
return 0;
|
||||
|
||||
init_listen_addrs();
|
||||
init_mcast_groups();
|
||||
init_bcast_addrs();
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void free_config()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
94
src/ac/conf.h
Normal file
94
src/ac/conf.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
This file is part of ac.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CONF_H
|
||||
#define __CONF_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <confuse.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
|
||||
|
||||
#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
|
35
src/ac/db.c
Normal file
35
src/ac/db.c
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
|
||||
|
||||
|
||||
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 ;
|
||||
|
||||
|
||||
}
|
341
src/ac/socklist.c
Normal file
341
src/ac/socklist.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
#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; i<socklist_len; i++){
|
||||
close(socklist[i].sockfd);
|
||||
}
|
||||
free(socklist);
|
||||
socklist=0;
|
||||
pthread_mutex_destroy(&socklist_mutex);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int find_reply_socket(struct sockaddr *sa,int bc)
|
||||
{
|
||||
int bestsockfd = -1;
|
||||
int i;
|
||||
for (i=0; i<socklist_len; i++){
|
||||
struct sockaddr_storage sn;
|
||||
memset(&sn,0,sizeof(sn));
|
||||
unsigned int snlen = sizeof(struct sockaddr_storage);
|
||||
|
||||
if (getsockname(socklist[i].sockfd,(struct sockaddr*)&sn,&snlen)<0){
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sa->sa_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;
|
||||
}
|
||||
|
||||
|
51
src/ac/socklist.h
Normal file
51
src/ac/socklist.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#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
|
149
src/ac/wtplist.c
Normal file
149
src/ac/wtplist.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
|
||||
#define MAX_WTPS 200
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#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; i<max_wtp_connections; i++){
|
||||
if (!wtplist[i])
|
||||
continue;
|
||||
|
||||
if ( sock_cmpaddr(&wtplist[i]->conn->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; i<max_wtp_connections; i++){
|
||||
if (!wtplist[i]){
|
||||
wtplist[i]=wtpman;
|
||||
return wtpman;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
void wtplist_remove(struct wtpman * wtpman)
|
||||
{
|
||||
connlist_remove(connlist,wtpman->conn);
|
||||
return;
|
||||
|
||||
/*
|
||||
printf("Remove wtpman %p\n",wtpman);
|
||||
int i;
|
||||
for (i=0; i<max_wtp_connections; i++){
|
||||
if (wtplist[i]==wtpman){
|
||||
printf("wtpman removed\n");
|
||||
wtplist[i]=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
18
src/ac/wtplist.h
Normal file
18
src/ac/wtplist.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef __WTPLIST_H
|
||||
#define __WPTLIST_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#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
|
286
src/ac/wtpman.c
Normal file
286
src/ac/wtpman.c
Normal file
@ -0,0 +1,286 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#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 <errno.h>
|
||||
|
||||
#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);
|
||||
}
|
62
src/ac/wtpman.h
Normal file
62
src/ac/wtpman.h
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef __WTPMAN_H
|
||||
#define __WTPMAN_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <semaphore.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#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
|
161
src/capwap/Makefile
Normal file
161
src/capwap/Makefile
Normal file
@ -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)
|
166
src/capwap/acinfo.c
Normal file
166
src/capwap/acinfo.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#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<len){
|
||||
if (len-sub<8)
|
||||
return -1;
|
||||
|
||||
uint32_t vendor = ntohl(*((uint32_t*)(msgelem+sub)));
|
||||
val = ntohl(*((uint32_t*)(msgelem+sub+4)));
|
||||
sublen = val&0xffff;
|
||||
sub+=8;
|
||||
if (vendor != 0){
|
||||
sub+=sublen;
|
||||
continue;
|
||||
}
|
||||
int subtype = val>>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;
|
||||
}
|
||||
|
||||
|
||||
|
62
src/capwap/acinfo.h
Normal file
62
src/capwap/acinfo.h
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef __ACINFO_H
|
||||
#define __ACINFO_H
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#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
|
||||
|
59
src/capwap/acinfo_print.c
Normal file
59
src/capwap/acinfo_print.c
Normal file
@ -0,0 +1,59 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
53
src/capwap/aciplist.c
Normal file
53
src/capwap/aciplist.c
Normal file
@ -0,0 +1,53 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
669
src/capwap/avltree.c
Normal file
669
src/capwap/avltree.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#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; y<tpw; y++){
|
||||
struct avlnode *r=ar[tpw*i+y];
|
||||
if(r){
|
||||
printf("%i(%i)",*(int*)(r->data),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 <time.h>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
//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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
*/
|
64
src/capwap/avltree.h
Normal file
64
src/capwap/avltree.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
|
564
src/capwap/avltree.old.c
Normal file
564
src/capwap/avltree.old.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#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; y<tpw; y++){
|
||||
struct avlnode *r=ar[tpw*i+y];
|
||||
if(r){
|
||||
printf("%i(%i)",*(int*)(r->data),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 <time.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
36
src/capwap/avltree_del_all.c
Normal file
36
src/capwap/avltree_del_all.c
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "avltree.h"
|
||||
|
||||
static void avltree_del_all0(struct avltree *t ,struct avlnode * n)
|
||||
{
|
||||
if (!n)
|
||||
return;
|
||||
avltree_del_all0(t,n->left);
|
||||
avltree_del_all0(t,n->right);
|
||||
avlnode_destroy(t,n);
|
||||
}
|
||||
|
||||
void avltree_del_all(struct avltree *t)
|
||||
{
|
||||
avltree_del_all0(t,t->root);
|
||||
t->root=0;
|
||||
}
|
||||
|
||||
|
51
src/capwap/avltree_foreach.c
Normal file
51
src/capwap/avltree_foreach.c
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
|
37
src/capwap/avltree_get.c
Normal file
37
src/capwap/avltree_get.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
338
src/capwap/capwap.h
Normal file
338
src/capwap/capwap.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __CAPWAP_H
|
||||
#define __CAPWAP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#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<<len)) & (src >> (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
|
29
src/capwap/capwap_ieee80211.h
Normal file
29
src/capwap/capwap_ieee80211.h
Normal file
@ -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
|
||||
|
25
src/capwap/capwap_msg_new.c
Normal file
25
src/capwap/capwap_msg_new.c
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "capwap.h"
|
||||
|
||||
struct capwap_msg * capwap_msg_new()
|
||||
{
|
||||
|
||||
|
||||
}
|
41
src/capwap/capwap_parse_ctrlhdr.c
Normal file
41
src/capwap/capwap_parse_ctrlhdr.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
117
src/capwap/conn.c
Normal file
117
src/capwap/conn.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
*/
|
147
src/capwap/conn.h
Normal file
147
src/capwap/conn.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __CONN_H
|
||||
#define __CONN_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <semaphore.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "fragman.h"
|
||||
#include "cwmsg.h"
|
||||
#include "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 */
|
||||
|
51
src/capwap/conn_get_message.c
Normal file
51
src/capwap/conn_get_message.c
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
152
src/capwap/conn_process_packet.c
Normal file
152
src/capwap/conn_process_packet.c
Normal file
@ -0,0 +1,152 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
50
src/capwap/conn_q_add_packet.c
Normal file
50
src/capwap/conn_q_add_packet.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
|
||||
|
32
src/capwap/conn_q_get_packet.c
Normal file
32
src/capwap/conn_q_get_packet.c
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "conn.h"
|
||||
|
||||
|
||||
uint8_t * conn_q_get_packet(struct conn * conn)
|
||||
{
|
||||
struct timespec timespec;
|
||||
clock_gettime(CLOCK_REALTIME,×pec);
|
||||
timespec.tv_sec++;
|
||||
|
||||
|
||||
// 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]);
|
||||
*/
|
||||
|
||||
}
|
||||
|
50
src/capwap/conn_q_recv_packet.c
Normal file
50
src/capwap/conn_q_recv_packet.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#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;
|
||||
}
|
34
src/capwap/conn_recv_packet.c
Normal file
34
src/capwap/conn_recv_packet.c
Normal file
@ -0,0 +1,34 @@
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
96
src/capwap/conn_send_cwmsg.c
Normal file
96
src/capwap/conn_send_cwmsg.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
51
src/capwap/conn_send_packet.c
Normal file
51
src/capwap/conn_send_packet.c
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include "sock.h"
|
||||
#include "conn.h"
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
|
||||
#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;
|
||||
}
|
98
src/capwap/connlist.c
Normal file
98
src/capwap/connlist.c
Normal file
@ -0,0 +1,98 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "conn.h"
|
||||
#include "sock.h"
|
||||
|
||||
|
||||
static int connlist_cmp(const void * d1,const void *d2)
|
||||
{
|
||||
struct conn * c1=(struct conn *) d1;
|
||||
struct conn * c2=(struct conn *) d2;
|
||||
|
||||
return sock_cmpaddr((struct sockaddr*)&c1->addr,(struct sockaddr*)&c2->addr,1);
|
||||
}
|
||||
|
||||
|
||||
struct connlist * connlist_create(int len)
|
||||
{
|
||||
|
||||
struct connlist * cl = malloc(sizeof(struct connlist));
|
||||
if (!cl)
|
||||
return 0;
|
||||
|
||||
|
||||
cl->t = avltree_create(connlist_cmp,0);
|
||||
|
||||
if (!cl->t){
|
||||
free(cl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&cl->connlist_mutex,NULL)){
|
||||
avltree_destroy(cl->t);
|
||||
free(cl);
|
||||
return 0;
|
||||
};
|
||||
|
||||
cl->len=len;
|
||||
|
||||
return cl;
|
||||
}
|
||||
|
||||
void connlist_lock(struct connlist * cl)
|
||||
{
|
||||
pthread_mutex_lock(&cl->connlist_mutex);
|
||||
}
|
||||
|
||||
void connlist_unlock(struct connlist * cl)
|
||||
{
|
||||
pthread_mutex_unlock(&cl->connlist_mutex);
|
||||
}
|
||||
|
||||
|
||||
void connlist_destroy(struct connlist * cl)
|
||||
{
|
||||
if (cl->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);
|
||||
}
|
||||
|
||||
|
||||
|
46
src/capwap/cw_foreach_msgelem.c
Normal file
46
src/capwap/cw_foreach_msgelem.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#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<len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
26
src/capwap/cw_log.c
Normal file
26
src/capwap/cw_log.c
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "cw_log.h"
|
||||
|
||||
void (*cw_log_cb)(int level,const char * fromat, ...) = CW_LOG_DEFAULT_LOG;
|
||||
const char * cw_log_name = "cw";
|
||||
|
76
src/capwap/cw_log.h
Normal file
76
src/capwap/cw_log.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#ifndef __CW_LOG_H
|
||||
#define __CW_LOG_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#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
|
116
src/capwap/cw_log_debug.c
Normal file
116
src/capwap/cw_log_debug.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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<len;i++){
|
||||
sprintf(pdst,"%02X ",data[i]&0xff);
|
||||
pdst+=3;
|
||||
if ((i+1)%rowlen==0){
|
||||
sprintf(pdst,"\n\t");
|
||||
pdst+=2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cw_log_debug_cbs[level]("%s",dst);
|
||||
|
||||
free (dst);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
int cw_log_debug_level=0;
|
||||
|
||||
void (*cw_log_debug_cbs[])(const char * fromat, ...) = {
|
||||
cw_log_debug0_,
|
||||
cw_log_debug1_,
|
||||
cw_log_debug2_
|
||||
};
|
||||
|
||||
|
36
src/capwap/cw_log_tofile.c
Normal file
36
src/capwap/cw_log_tofile.c
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#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();
|
||||
}
|
||||
|
||||
|
20
src/capwap/cw_log_tosyslog.c
Normal file
20
src/capwap/cw_log_tosyslog.c
Normal file
@ -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();
|
||||
}
|
||||
|
||||
|
12
src/capwap/cw_msgelemtostr.c
Normal file
12
src/capwap/cw_msgelemtostr.c
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
|
||||
:q
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const cw_msgelemtostr(int elem)
|
||||
{
|
||||
|
||||
}
|
36
src/capwap/cw_pseudo_rand.c
Normal file
36
src/capwap/cw_pseudo_rand.c
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
int cw_pseudo_rand(uint8_t *dst, int len)
|
||||
{
|
||||
static int init = 1;
|
||||
if (init){
|
||||
srand(time(NULL));
|
||||
}
|
||||
int i;
|
||||
for (i=0; i<len; i++){
|
||||
dst[i]=rand();
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
61
src/capwap/cw_rand.c
Normal file
61
src/capwap/cw_rand.c
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#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<len){
|
||||
cw_log_debug2("Not enough entropy reading from %s, using pseudo rand",cw_rand_dev);
|
||||
return cw_pseudo_rand(dst,len);
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
34
src/capwap/cw_setstr.c
Normal file
34
src/capwap/cw_setstr.c
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "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;
|
||||
}
|
||||
|
||||
|
31
src/capwap/cw_util.h
Normal file
31
src/capwap/cw_util.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
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);
|
||||
|
||||
|
34
src/capwap/cwmsg.h
Normal file
34
src/capwap/cwmsg.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef __CWMSG_H
|
||||
#define __CWMSG_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
32
src/capwap/cwmsg_addelem.c
Normal file
32
src/capwap/cwmsg_addelem.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
57
src/capwap/cwmsg_addelem_ac_descriptor.c
Normal file
57
src/capwap/cwmsg_addelem_ac_descriptor.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#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);
|
||||
|
||||
}
|
||||
|
||||
|
103
src/capwap/cwmsg_addelem_ctrl_ip_addrs.c
Normal file
103
src/capwap/cwmsg_addelem_ctrl_ip_addrs.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#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; i<acinfo->salist_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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
55
src/capwap/cwmsg_addelem_cw_local_ip_addr.c
Normal file
55
src/capwap/cwmsg_addelem_cw_local_ip_addr.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "capwap.h"
|
||||
#include "cwmsg.h"
|
||||
#include "conn.h"
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
19
src/capwap/cwmsg_addelem_mtu_discovery_padding.c
Normal file
19
src/capwap/cwmsg_addelem_mtu_discovery_padding.c
Normal file
@ -0,0 +1,19 @@
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
10
src/capwap/cwmsg_addelem_result_code.c
Normal file
10
src/capwap/cwmsg_addelem_result_code.c
Normal file
@ -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);
|
||||
}
|
||||
|
37
src/capwap/cwmsg_addelem_wtp_board_data.c
Normal file
37
src/capwap/cwmsg_addelem_wtp_board_data.c
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
57
src/capwap/cwmsg_addelem_wtp_descriptor.c
Normal file
57
src/capwap/cwmsg_addelem_wtp_descriptor.c
Normal file
@ -0,0 +1,57 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
39
src/capwap/cwmsg_addelem_wtp_radio_infos.c
Normal file
39
src/capwap/cwmsg_addelem_wtp_radio_infos.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "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]);
|
||||
}
|
||||
|
||||
}
|
62
src/capwap/cwmsg_init.c
Normal file
62
src/capwap/cwmsg_init.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
28
src/capwap/cwmsg_init_echo_request.c
Normal file
28
src/capwap/cwmsg_init_echo_request.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
|
91
src/capwap/cwmsg_send.c
Normal file
91
src/capwap/cwmsg_send.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
|
||||
|
13
src/capwap/cwmsg_set_control_header.c
Normal file
13
src/capwap/cwmsg_set_control_header.c
Normal file
@ -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);
|
||||
}
|
||||
|
||||
|
61
src/capwap/cwread_discovery_response.c
Normal file
61
src/capwap/cwread_discovery_response.c
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "capwap.h"
|
||||
#include "acinfo.h"
|
||||
#include "cw_util.h"
|
||||
#include "cw_log.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
58
src/capwap/cwread_join_response.c
Normal file
58
src/capwap/cwread_join_response.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
|
||||
|
18
src/capwap/cwrmsg.h
Normal file
18
src/capwap/cwrmsg.h
Normal file
@ -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
|
39
src/capwap/cwsend_discovery_request.c
Normal file
39
src/capwap/cwsend_discovery_request.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "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);
|
||||
}
|
47
src/capwap/cwsend_discovery_response.c
Normal file
47
src/capwap/cwsend_discovery_response.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
33
src/capwap/cwsend_echo_request.c
Normal file
33
src/capwap/cwsend_echo_request.c
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "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);
|
||||
}
|
17
src/capwap/cwsend_echo_response.c
Normal file
17
src/capwap/cwsend_echo_response.c
Normal file
@ -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);
|
||||
|
||||
}
|
52
src/capwap/cwsend_join_request.c
Normal file
52
src/capwap/cwsend_join_request.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
26
src/capwap/cwsend_join_response.c
Normal file
26
src/capwap/cwsend_join_response.c
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
30
src/capwap/dtls.h
Normal file
30
src/capwap/dtls.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#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
|
||||
|
379
src/capwap/dtls_openssl.c
Normal file
379
src/capwap/dtls_openssl.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include <errno.h>
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
|
||||
#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 <arpa/inet.h>
|
||||
//#include <socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
48
src/capwap/dtls_openssl.h
Normal file
48
src/capwap/dtls_openssl.h
Normal file
@ -0,0 +1,48 @@
|
||||
#ifndef __DTLS_OPENSLL_H
|
||||
#define __DTLS_OPENSSL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#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
|
160
src/capwap/dtls_openssl_accept.c
Normal file
160
src/capwap/dtls_openssl_accept.c
Normal file
@ -0,0 +1,160 @@
|
||||
#include <openssl/err.h>
|
||||
|
||||
#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);
|
||||
*/
|
||||
}
|
||||
|
||||
|
171
src/capwap/dtls_openssl_bio.c
Normal file
171
src/capwap/dtls_openssl_bio.c
Normal file
@ -0,0 +1,171 @@
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
98
src/capwap/dtls_openssl_connect.c
Normal file
98
src/capwap/dtls_openssl_connect.c
Normal file
@ -0,0 +1,98 @@
|
||||
#include <openssl/err.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
41
src/capwap/dtls_openssl_init.c
Normal file
41
src/capwap/dtls_openssl_init.c
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
203
src/capwap/fragman.c
Normal file
203
src/capwap/fragman.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#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;i<FRAG_MAXIDS; i++){
|
||||
if (frags[i].buffer==NULL)
|
||||
continue;
|
||||
if (frags[i].fragid==fragid)
|
||||
{
|
||||
return &frags[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* create a new fragment
|
||||
*/
|
||||
static struct frag * frag_new(struct frag * frags, int fragid)
|
||||
{
|
||||
struct timespec t;
|
||||
clock_gettime(CLOCK_REALTIME,&t);
|
||||
|
||||
int i;
|
||||
for (i=0; i<FRAG_MAXIDS; i++){
|
||||
if (frags[i].buffer==NULL || (t.tv_sec - frags[i].t.tv_sec>FRAG_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; i<FRAG_MAXIDS; i++){
|
||||
if (frags[i]->fragid==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<FRAG_MAXIDS; i++){
|
||||
if (frags[i].buffer==NULL)
|
||||
continue;
|
||||
free(frags[i].buffer);
|
||||
}
|
||||
free (frags);
|
||||
}
|
||||
|
64
src/capwap/fragman.h
Normal file
64
src/capwap/fragman.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __FRAGMAN_H
|
||||
#define __FRAGMAN_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#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
|
||||
|
48
src/capwap/process_discovery_request.c
Normal file
48
src/capwap/process_discovery_request.c
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
#include <stdio.h> //tube
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
|
||||
|
55
src/capwap/process_join_request.c
Normal file
55
src/capwap/process_join_request.c
Normal file
@ -0,0 +1,55 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_ieee80211.h"
|
||||
|
||||
#include <stdio.h> //Tube
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
53
src/capwap/process_msgelems.c
Normal file
53
src/capwap/process_msgelems.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#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<len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
60
src/capwap/process_msgelems_discovery_request.c
Normal file
60
src/capwap/process_msgelems_discovery_request.c
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "capwap.h"
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
*/
|
32
src/capwap/radioinfo.h
Normal file
32
src/capwap/radioinfo.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __RADIOINFO_H
|
||||
#define __RADIOINFO_H
|
||||
|
||||
struct radioinfo{
|
||||
int rid;
|
||||
uint32_t type;
|
||||
#ifdef WITH_RMAC_SUPPORT
|
||||
uint8_t * rmac;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
70
src/capwap/sock.h
Normal file
70
src/capwap/sock.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __SOCK_H
|
||||
#define __SOCK_H
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
|
||||
#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 */
|
||||
|
22
src/capwap/sock_addrinit.c
Normal file
22
src/capwap/sock_addrinit.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
61
src/capwap/sock_addrlen.c
Normal file
61
src/capwap/sock_addrlen.c
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#ifdef AF_LINK
|
||||
# include <net/if_dl.h>
|
||||
#endif
|
||||
#ifdef AF_PACKET
|
||||
# include <netpacket/packet.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
}
|
||||
|
95
src/capwap/sock_addrtostr.c
Normal file
95
src/capwap/sock_addrtostr.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#ifdef AF_LINK
|
||||
# include <net/if_dl.h>
|
||||
#endif
|
||||
#ifdef AF_PACKET
|
||||
# include <netpacket/packet.h>
|
||||
#endif
|
||||
|
||||
#include "sock.h"
|
||||
|
||||
/*
|
||||
void sock_hwaddrtostr(const uint8_t *haddr,int len,char *dst)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<len-1; i++){
|
||||
sprintf(dst,"%02X:",haddr[i]);
|
||||
dst+=3;
|
||||
}
|
||||
sprintf(dst,"%02X",haddr[i]);
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
char *sock_addrtostr(const struct sockaddr *sa, char *s, size_t maxlen)
|
||||
{
|
||||
|
||||
int port;
|
||||
|
||||
switch(sa->sa_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; i<sl->sll_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;
|
||||
}
|
78
src/capwap/sock_cmpaddr.c
Normal file
78
src/capwap/sock_cmpaddr.c
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
28
src/capwap/sock_copyaddr.c
Normal file
28
src/capwap/sock_copyaddr.c
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
|
||||
}
|
||||
|
65
src/capwap/sock_create.c
Normal file
65
src/capwap/sock_create.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
31
src/capwap/sock_getbroadcastaddr.c
Normal file
31
src/capwap/sock_getbroadcastaddr.c
Normal file
@ -0,0 +1,31 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
72
src/capwap/sock_getifaddr.c
Normal file
72
src/capwap/sock_getifaddr.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
39
src/capwap/sock_getifhwaddr.c
Normal file
39
src/capwap/sock_getifhwaddr.c
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifdef AF_LINK
|
||||
# include <net/if_dl.h>
|
||||
#endif
|
||||
#ifdef AF_PACKET
|
||||
# include <netpacket/packet.h>
|
||||
#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;
|
||||
}
|
35
src/capwap/sock_getport.c
Normal file
35
src/capwap/sock_getport.c
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "sock.h"
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
33
src/capwap/sock_hwaddrtostr.c
Normal file
33
src/capwap/sock_hwaddrtostr.c
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sock.h"
|
||||
|
||||
void sock_hwaddrtostr(const uint8_t *haddr,int len,char *dst)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<len-1; i++){
|
||||
sprintf(dst,"%02X:",haddr[i]);
|
||||
dst+=3;
|
||||
}
|
||||
sprintf(dst,"%02X",haddr[i]);
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user