Initial commit

FossilOrigin-Name: c53d95729c009f8f80a7d63847cef7668ff73f8af0523ab65f7734696f85399c
This commit is contained in:
7u83@mail.ru 2014-07-11 20:12:11 +00:00
parent 3234327f71
commit 2bae9358d7
136 changed files with 11071 additions and 0 deletions

63
src/ac/Makefile Normal file
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,2 @@
#define AC_MAX_LISTEN_SOCKETS 32

493
src/ac/conf.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}

View File

@ -0,0 +1,36 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#include "avltree.h"
static void avltree_del_all0(struct avltree *t ,struct avlnode * n)
{
if (!n)
return;
avltree_del_all0(t,n->left);
avltree_del_all0(t,n->right);
avlnode_destroy(t,n);
}
void avltree_del_all(struct avltree *t)
{
avltree_del_all0(t,t->root);
t->root=0;
}

View File

@ -0,0 +1,51 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#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
View 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
View 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

View 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

View File

@ -0,0 +1,25 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#include "capwap.h"
struct capwap_msg * capwap_msg_new()
{
}

View File

@ -0,0 +1,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
View 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
View 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 */

View 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;
}

View 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;
}

View File

@ -0,0 +1,50 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#include <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);
}

View 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,&timespec);
timespec.tv_sec++;
// sem_wait(&conn->q_sem);
if (sem_timedwait(&conn->q_sem,&timespec)==-1){
return NULL;
};
int qrpos = conn->qrpos+1;
if (qrpos==conn->qsize)
qrpos=0;
conn->qrpos=qrpos;
return conn->q[qrpos];
/*
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]);
*/
}

View File

@ -0,0 +1,50 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#include <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;
}

View 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;
}

View 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);
}

View File

@ -0,0 +1,51 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#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
View 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);
}

View 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
View 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
View File

@ -0,0 +1,76 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#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
View 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_
};

View 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();
}

View 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();
}

View File

@ -0,0 +1,12 @@
:q
const cw_msgelemtostr(int elem)
{
}

View File

@ -0,0 +1,36 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#include <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
View File

@ -0,0 +1,61 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#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
View 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
View 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
View 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

View 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;
}

View 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);
}

View 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
}
}
}

View 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
}
}

View 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;
}

View 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);
}

View 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);
}

View 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);
}

View File

@ -0,0 +1,39 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#include "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
View 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;
}

View 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
View 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);
}

View 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);
}

View File

@ -0,0 +1,61 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#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);
}

View 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
View 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

View File

@ -0,0 +1,39 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#include "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);
}

View File

@ -0,0 +1,47 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#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);
}

View File

@ -0,0 +1,33 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#include "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);
}

View 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);
}

View File

@ -0,0 +1,52 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#include <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);
}

View 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
View 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
View 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
View 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

View 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);
*/
}

View 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;
}

View 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;
}

View 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
View 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
View 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

View 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);
}

View 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);
}

View 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;
}

View 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
View 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
View 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 */

View 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
View File

@ -0,0 +1,61 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#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;
}
}

View 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
View File

@ -0,0 +1,78 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#include <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);
}

View 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
View 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;
}

View 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;
}

View 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;
}

View 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
View File

@ -0,0 +1,35 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#include "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;
}

View File

@ -0,0 +1,33 @@
/*
This file is part of libcapwap.
libcapwap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libcapwap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
#include <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