Initial commit
FossilOrigin-Name: c53d95729c009f8f80a7d63847cef7668ff73f8af0523ab65f7734696f85399c
This commit is contained in:
parent
3234327f71
commit
2bae9358d7
63
src/ac/Makefile
Normal file
63
src/ac/Makefile
Normal file
@ -0,0 +1,63 @@
|
||||
ifndef CC
|
||||
CC=gcc
|
||||
endif
|
||||
SYSARCH := $(shell uname -m)
|
||||
ifndef ARCH
|
||||
ARCH=$(SYSARCH)
|
||||
endif
|
||||
|
||||
LDFLAGS = -g -D_REENTRANT -L/usr/local/lib -L../capwap/$(ARCH)
|
||||
|
||||
CFLAGS = -Wall -g -O0 -D_REENTRANT -DCW_NO_DTLS -DIPV6 -I/usr/local/include -I../capwap
|
||||
|
||||
|
||||
LIBS+=-lcapwap
|
||||
LIBS+=-lrt
|
||||
LIBS+=-lssl
|
||||
LIBS+=-lcrypto
|
||||
LIBS+=-lpthread
|
||||
LIBS+=-lconfuse
|
||||
LIBS+=-lsqlite3
|
||||
|
||||
|
||||
|
||||
CFLAGS += -DWITH_CW_LOG
|
||||
CFLAGS += -DWITH_CW_LOG_DEBUG
|
||||
CFLAGS += -DWITH_RMAC_SUPPORT
|
||||
CFLAGS += -DWITH_DTLS
|
||||
CFLAGS += -DWITH_IPV6
|
||||
|
||||
RM = /bin/rm -f
|
||||
|
||||
# list of generated object files for AC.
|
||||
AC_OBJS = wtplist.o wtpman.o conf.o ac_main.o \
|
||||
ac_interface.o \
|
||||
socklist.o \
|
||||
db.o \
|
||||
|
||||
AC_SRCS = $(AC_OBJS:.o=.c)
|
||||
AC_DEPS := $(AC_OBJS:.o=.d)
|
||||
|
||||
AC_NAME = actube
|
||||
|
||||
.PHONY: deps clean clean_libs libs
|
||||
|
||||
# top-level rule, to compile everything.
|
||||
all: $(AC_NAME)
|
||||
|
||||
#$(WTP_NAME) $(WUA_NAME)
|
||||
|
||||
$(AC_NAME): $(AC_OBJS)
|
||||
$(CC) $(AC_OBJS) $(CC_FLAGS) $(OPENSSL_INCLUDE) -o $(AC_NAME) $(LDFLAGS) $(LIBS)
|
||||
|
||||
|
||||
clean:
|
||||
$(RM) $(AC_NAME) $(AC_OBJS) $(AC_DEPS)
|
||||
|
||||
clean_deps:
|
||||
$(AC_DEPS)
|
||||
|
||||
deps: $(AC_SRC)
|
||||
$(CC) -MD -E $(AC_SRCS) $(CFLAGS) >/dev/null
|
||||
|
||||
-include $(AC_DEPS)
|
27
src/ac/ac.default.conf
Normal file
27
src/ac/ac.default.conf
Normal file
@ -0,0 +1,27 @@
|
||||
#
|
||||
# Use IPv4 protocol
|
||||
#
|
||||
# ipv4=true
|
||||
|
||||
#
|
||||
# Use IPv6 protocol
|
||||
#
|
||||
# ipv6=true
|
||||
#
|
||||
|
||||
# Listen addresses
|
||||
#
|
||||
# listen =
|
||||
# listen = 192.168.0.15
|
||||
|
||||
|
||||
#
|
||||
# dtls_psk =
|
||||
#
|
||||
# dtls_psk =
|
||||
|
||||
|
||||
# ac_name
|
||||
# The name reported by actube
|
||||
#
|
||||
# ac_name = AC
|
102
src/ac/ac_interface.c
Normal file
102
src/ac/ac_interface.c
Normal file
@ -0,0 +1,102 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "sock.h"
|
||||
|
||||
#include "socklist.h"
|
||||
#include "acinfo.h"
|
||||
#include "conf.h"
|
||||
|
||||
#include "capwap.h"
|
||||
|
||||
ACIPLIST * get_aciplist()
|
||||
{
|
||||
int i=0;
|
||||
|
||||
ACIPLIST * aciplist = aciplist_create();
|
||||
if(!aciplist)
|
||||
return 0;
|
||||
|
||||
|
||||
for (i=0; i<socklist_len;i++){
|
||||
|
||||
if (socklist[i].type != SOCKLIST_UNICAST_SOCKET)
|
||||
break;
|
||||
|
||||
struct sockaddr_storage sa;
|
||||
unsigned int salen=sizeof(sa);
|
||||
if ( getsockname(socklist[i].sockfd,(struct sockaddr*)&sa,&salen)<0)
|
||||
continue;
|
||||
|
||||
ACIP * acip;
|
||||
acip = malloc(sizeof(ACIP));
|
||||
if (!acip)
|
||||
continue;
|
||||
|
||||
sock_copyaddr(&acip->ip,(struct sockaddr*)&sa);
|
||||
acip->wtp_count=17;
|
||||
|
||||
|
||||
aciplist_add(aciplist,acip);
|
||||
|
||||
|
||||
}
|
||||
return aciplist;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct ac_info * get_acinfo()
|
||||
{
|
||||
|
||||
struct ac_info * acinfo;
|
||||
acinfo = malloc(sizeof(struct ac_info));
|
||||
if(!acinfo)
|
||||
return 0;
|
||||
|
||||
memset(acinfo,0,sizeof(struct ac_info));
|
||||
acinfo->ac_name=conf_acname;
|
||||
|
||||
acinfo->stations=10;
|
||||
acinfo->limit=10000;
|
||||
acinfo->active_wtps=10;
|
||||
acinfo->max_wtps=conf_max_wtps;
|
||||
acinfo->rmac=2; /* radio mac not supported */
|
||||
|
||||
acinfo->vendor_id=conf_vendor_id;
|
||||
acinfo->hardware_version=(uint8_t*)conf_hardware_version;
|
||||
acinfo->software_version=(uint8_t*)conf_software_version;
|
||||
|
||||
if (conf_dtls_psk)
|
||||
acinfo->security|=AC_SECURITY_S;
|
||||
|
||||
acinfo->dtls_policy = AC_DTLS_POLICY_C;
|
||||
// acinfo->ac_ips = conf_ac_ips;
|
||||
// acinfo->ac_ips_len=conf_ac_ips_len;
|
||||
|
||||
// acinfo->salist=conf_salist;
|
||||
// acinfo->salist_len=conf_salist_len;
|
||||
|
||||
// acinfo->salist = conf_ac_ips;
|
||||
// acinfo->salist_len = conf_ac_ips_len;
|
||||
|
||||
acinfo->aciplist=get_aciplist();
|
||||
|
||||
|
||||
return acinfo;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
get_join_result()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
219
src/ac/ac_main.c
Normal file
219
src/ac/ac_main.c
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
This file is part of actube.
|
||||
|
||||
actube is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "actube.h"
|
||||
#include "wtplist.h"
|
||||
#include "dtls.h"
|
||||
#include "cw_log.h"
|
||||
#include "conf.h"
|
||||
#include "sock.h"
|
||||
|
||||
#include "socklist.h"
|
||||
|
||||
int ac_run();
|
||||
|
||||
int main (int argc, const char * argv[])
|
||||
{
|
||||
|
||||
cw_log_name="AC-Tube";
|
||||
|
||||
read_config("ac.conf");
|
||||
cw_log_debug_level=conf_debug_level;
|
||||
|
||||
test_db();
|
||||
|
||||
|
||||
|
||||
cw_log(LOG_INFO,"Starting AC-Tube");
|
||||
|
||||
#ifdef WITH_DTLS
|
||||
dtls_init();
|
||||
#endif
|
||||
if (!socklist_init())
|
||||
goto errX;
|
||||
|
||||
if (!wtplist_init())
|
||||
goto errX;
|
||||
|
||||
|
||||
int rc = ac_run();
|
||||
errX:
|
||||
wtplist_destroy();
|
||||
socklist_destroy();
|
||||
return rc;
|
||||
}
|
||||
|
||||
void process_ctrl_packet(int index, struct sockaddr * addr, uint8_t * buffer, int len);
|
||||
|
||||
int ac_run()
|
||||
{
|
||||
|
||||
if (!conf_listen_addrs_len){
|
||||
cw_log(LOG_ERR,"Fatal error: No listen addresses found.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* it is important to create the unicast sockets first,
|
||||
* because when we create the mcast an bcast sockets next
|
||||
* we will look for already created sockets to find a
|
||||
* good unicast reply socket */
|
||||
|
||||
int i;
|
||||
for(i=0; i<conf_listen_addrs_len; i++){
|
||||
socklist_add_unicast(conf_listen_addrs[i],conf_control_port);
|
||||
}
|
||||
|
||||
if (socklist_len==0){
|
||||
cw_log(LOG_ERR,"Fatal error: Could not setup any listen socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* create multicast sockets */
|
||||
for (i=0; i<conf_mcast_groups_len;i++){
|
||||
socklist_add_multicast(conf_mcast_groups[i],conf_control_port);
|
||||
}
|
||||
|
||||
/* broadcast sockety ipv4 only */
|
||||
for (i=0; i<conf_bcast_addrs_len;i++){
|
||||
socklist_add_broadcast(conf_bcast_addrs[i],conf_control_port);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
while(1){
|
||||
|
||||
/* prepare fdset */
|
||||
fd_set fset;
|
||||
int max = 0;
|
||||
FD_ZERO(&fset);
|
||||
for (i=0; i<socklist_len; i++){
|
||||
FD_SET(socklist[i].sockfd,&fset);
|
||||
if (socklist[i].sockfd>max)
|
||||
max=socklist[i].sockfd;
|
||||
}
|
||||
|
||||
/* wait for an event */
|
||||
int n;
|
||||
while((n=select(max+1, &fset, NULL, NULL, NULL)) < 0) {
|
||||
if (errno != EINTR)
|
||||
return n;
|
||||
|
||||
}
|
||||
|
||||
/* process the received packet */
|
||||
for( i=0; i<socklist_len; i++){
|
||||
|
||||
if (!FD_ISSET(socklist[i].sockfd,&fset))
|
||||
continue;
|
||||
|
||||
struct sockaddr_storage srcaddr;
|
||||
socklen_t sockaddrlen;
|
||||
|
||||
memset(&srcaddr,0,sizeof(struct sockaddr_storage));
|
||||
sockaddrlen = sizeof(struct sockaddr_storage);
|
||||
|
||||
uint8_t buffer[4096];
|
||||
int len = sock_receive(socklist[i].sockfd,
|
||||
buffer, sizeof(buffer),
|
||||
0,
|
||||
(struct sockaddr*)&srcaddr, &sockaddrlen);
|
||||
|
||||
process_ctrl_packet(i, (struct sockaddr*)&srcaddr,buffer,len);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* close and free all sockts */
|
||||
for(i=0; i<socklist_len; i++){
|
||||
// close(socklist[i]);
|
||||
}
|
||||
free(socklist);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void process_ctrl_packet(int index,struct sockaddr * addr, uint8_t * buffer, int len)
|
||||
{
|
||||
int sock = socklist[index].reply_sockfd;
|
||||
|
||||
#ifdef WITH_CW_LOG_DEBUG
|
||||
char str[100];
|
||||
sock_addrtostr(addr,str,100);
|
||||
cw_log_debug0("Received packet from %s, len = %i, via %s\n",str,len,
|
||||
socklist[index].type==SOCKLIST_UNICAST_SOCKET ? "unicast":"bcast/mcast");
|
||||
cw_log_debug2_dump(buffer,len,"Packet data for packet, recevied from %s",str);
|
||||
#endif
|
||||
|
||||
/* first of all check preamble */
|
||||
int preamble = CWTH_GET_PREAMBLE(buffer);
|
||||
|
||||
#ifdef WITH_DTLS
|
||||
if (preamble != CAPWAP_PACKET_PREAMBLE && preamble != CAPWAP_DTLS_PACKET_PREAMBLE){
|
||||
#else
|
||||
if (preamble != CAPWAP_PACKET_PREAMBLE ){
|
||||
#endif
|
||||
cw_log_debug0("Discarding packet, wrong preamble, preamble = 0x%01X",preamble);
|
||||
return;
|
||||
}
|
||||
|
||||
wtplist_lock();
|
||||
struct wtpman * wtpman = wtplist_get(addr);
|
||||
if (!wtpman){
|
||||
|
||||
wtpman = wtpman_create(index,addr);
|
||||
|
||||
if (!wtpman ){
|
||||
cw_log(LOG_ERR,"Error creating wtpman: %s",strerror(errno));
|
||||
wtplist_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!wtplist_add(wtpman)){
|
||||
cw_log(LOG_ERR,"Error adding wtpman: Too many wtp connections");
|
||||
wtpman_destroy(wtpman);
|
||||
wtplist_unlock();
|
||||
return;
|
||||
};
|
||||
|
||||
wtpman_start(wtpman,preamble & 0xf);
|
||||
}
|
||||
|
||||
wtpman_addpacket(wtpman,buffer,len);
|
||||
wtplist_unlock();
|
||||
}
|
||||
|
||||
|
||||
|
2
src/ac/actube.h
Normal file
2
src/ac/actube.h
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
#define AC_MAX_LISTEN_SOCKETS 32
|
493
src/ac/conf.c
Normal file
493
src/ac/conf.c
Normal file
@ -0,0 +1,493 @@
|
||||
/*
|
||||
This file is part of actube.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <confuse.h>
|
||||
|
||||
#include "capwap.h"
|
||||
#include "sock.h"
|
||||
|
||||
#include "conf.h"
|
||||
|
||||
#include "cw_log.h"
|
||||
#include "cw_util.h"
|
||||
|
||||
char * conf_acname = NULL;
|
||||
int conf_acname_len = 0;
|
||||
|
||||
long conf_max_wtps = CONF_DEFAULT_MAXWTPS;
|
||||
char * conf_logfilename=CONF_DEFAULT_LOGFILENAME;
|
||||
struct sockaddr_storage * conf_salist=NULL;
|
||||
|
||||
char ** conf_listen_addrs;
|
||||
int conf_listen_addrs_len=0;
|
||||
|
||||
|
||||
char ** conf_mcast_groups=0;
|
||||
int conf_mcast_groups_len=0;
|
||||
|
||||
char ** conf_bcast_addrs=0;
|
||||
int conf_bcast_addrs_len;
|
||||
|
||||
|
||||
struct sockaddr_storage * conf_bsalist=NULL;
|
||||
|
||||
int conf_salist_len=0;
|
||||
int conf_bsalist_len=0;
|
||||
|
||||
struct sockaddr * conf_ac_ips;
|
||||
int conf_ac_ips_len;
|
||||
|
||||
char * conf_sslcertfilename=NULL;
|
||||
char * conf_sslkeyfilename=NULL;
|
||||
char * conf_dtls_psk=NULL;
|
||||
|
||||
char * conf_ac_hardware_version=NULL;
|
||||
char * conf_ac_software_version=NULL;
|
||||
int conf_security=0;
|
||||
long conf_vendor_id=CONF_DEFAULT_VENDOR_ID;
|
||||
|
||||
char * conf_hardware_version;
|
||||
char * conf_software_version;
|
||||
|
||||
int conf_use_loopback = 0;
|
||||
|
||||
long conf_debug_level=-1;
|
||||
|
||||
char * conf_db_file =0;
|
||||
|
||||
int conf_ipv4=1;
|
||||
#ifdef WITH_IPV6
|
||||
int conf_ipv6=1;
|
||||
#endif
|
||||
|
||||
|
||||
char * conf_control_port=0;
|
||||
cfg_bool_t conf_ignore_wtp_source_port = cfg_false;
|
||||
|
||||
static int init_acname()
|
||||
{
|
||||
if (conf_acname == NULL){
|
||||
conf_acname=CONF_DEFAULT_ACNAME;
|
||||
}
|
||||
conf_acname_len=strlen(conf_acname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int init_dtls()
|
||||
{
|
||||
if (conf_dtls_psk!=NULL){
|
||||
conf_security=CWACSECURITY_FLAGS_S;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int init_vendor_id()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int init_version()
|
||||
{
|
||||
if (!conf_hardware_version)
|
||||
{
|
||||
struct utsname u;
|
||||
int rc = uname(&u);
|
||||
if (rc<0)
|
||||
conf_hardware_version=CONF_DEFAULT_HARDWARE_VERSION;
|
||||
else{
|
||||
char str[265];
|
||||
sprintf(str,"%s / %s %s",u.machine,u.sysname,u.release);
|
||||
conf_hardware_version=strdup(str);
|
||||
}
|
||||
}
|
||||
if (!conf_software_version)
|
||||
conf_software_version=CONF_DEFAULT_SOFTWARE_VERSION;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int init_control_port()
|
||||
{
|
||||
if (conf_control_port != 0)
|
||||
return 1;
|
||||
|
||||
char str[30];
|
||||
sprintf(str,"%d",CONF_DEFAULT_CONTROL_PORT);
|
||||
conf_control_port=(char*)cw_setstr((uint8_t**)&conf_control_port,(uint8_t*)str,strlen(str));
|
||||
return 1;
|
||||
}
|
||||
|
||||
#include <ifaddrs.h>
|
||||
|
||||
static int init_listen_addrs()
|
||||
{
|
||||
if (conf_listen_addrs!=0)
|
||||
return 1;
|
||||
|
||||
struct ifaddrs * ifap,*ifa;
|
||||
|
||||
int rc = getifaddrs(&ifap);
|
||||
if (rc==-1)
|
||||
return 0;
|
||||
|
||||
/* count the addresses */
|
||||
int ctr=0;
|
||||
for (ifa=ifap; ifa!=0; ifa=ifa->ifa_next){
|
||||
if (ifa->ifa_addr->sa_family==AF_INET && conf_ipv4)
|
||||
ctr++;
|
||||
#ifdef WITH_IPV6
|
||||
if (ifa->ifa_addr->sa_family==AF_INET6 && conf_ipv6)
|
||||
ctr++;
|
||||
#endif
|
||||
}
|
||||
|
||||
conf_listen_addrs = malloc(sizeof(char*)*ctr);
|
||||
if (!conf_listen_addrs){
|
||||
rc=0;
|
||||
goto errX;
|
||||
}
|
||||
memset(conf_listen_addrs,0,sizeof(char*)*ctr);
|
||||
|
||||
|
||||
ctr=0;
|
||||
/* get the addresses */
|
||||
for (ifa=ifap; ifa!=0; ifa=ifa->ifa_next){
|
||||
char str[100];
|
||||
|
||||
if(!conf_use_loopback){
|
||||
if ((ifa->ifa_flags & IFF_LOOPBACK)){
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (ifa->ifa_addr->sa_family==AF_INET && conf_ipv4){
|
||||
sock_addrtostr(ifa->ifa_addr,str,100);
|
||||
*strchr(str,':')=0;
|
||||
conf_listen_addrs[ctr]=(char*)cw_setstr((uint8_t**)&conf_listen_addrs[ctr],(uint8_t*)str,strlen(str));
|
||||
if (conf_listen_addrs[ctr])
|
||||
ctr++;
|
||||
|
||||
}
|
||||
#ifdef WITH_IPV6
|
||||
if (ifa->ifa_addr->sa_family==AF_INET6 && conf_ipv6){
|
||||
sock_addrtostr(ifa->ifa_addr,str,100);
|
||||
if (strncmp(str,"fe80:",5)==0){
|
||||
strcat(str,"%");
|
||||
strcat(str,ifa->ifa_name);
|
||||
}
|
||||
conf_listen_addrs[ctr]=(char*)cw_setstr((uint8_t**)&conf_listen_addrs[ctr],(uint8_t*)str,strlen(str));
|
||||
if (conf_listen_addrs[ctr])
|
||||
ctr++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
conf_listen_addrs_len=ctr;
|
||||
rc=1;
|
||||
errX:
|
||||
freeifaddrs(ifap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static char * conf_default_mcast_groups_ipv4[] = {
|
||||
"224.0.1.140",
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef WITH_IPV6
|
||||
static char * conf_default_mcast_groups_ipv6[] = {
|
||||
/* "ff01:0:0:0:0:0:0:18c",
|
||||
"ff02:0:0:0:0:0:0:18c%em0",
|
||||
"ff03:0:0:0:0:0:0:18c",
|
||||
"ff04:0:0:0:0:0:0:18c",
|
||||
"ff05:0:0:0:0:0:0:18c",
|
||||
"ff06:0:0:0:0:0:0:18c"
|
||||
*/
|
||||
};
|
||||
#endif
|
||||
|
||||
//#include "avltree"
|
||||
#include "stravltree.h"
|
||||
|
||||
|
||||
|
||||
static int add_bcast_addr(void *priv, void * addr)
|
||||
{
|
||||
char *s = (char*)addr;
|
||||
conf_bcast_addrs[conf_bcast_addrs_len]=strdup(s);
|
||||
if (conf_bcast_addrs[conf_bcast_addrs_len]!=0)
|
||||
conf_bcast_addrs_len++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize broadcast addresses (ipv4 only)
|
||||
*/
|
||||
int init_bcast_addrs()
|
||||
{
|
||||
if (conf_bcast_addrs)
|
||||
return 1;
|
||||
|
||||
if (!conf_ipv4)
|
||||
return 1;
|
||||
|
||||
struct avltree *t = stravltree_create();
|
||||
if (!t)
|
||||
return 0;
|
||||
|
||||
/* add the default broadast address */
|
||||
stravltree_add(t,"255.255.255.255");
|
||||
|
||||
|
||||
/* add all other local broadcast addresses */
|
||||
struct ifaddrs * ifa0,*ifa;
|
||||
int rc = getifaddrs(&ifa0);
|
||||
if (rc==-1)
|
||||
return 0;
|
||||
|
||||
for (ifa=ifa0; ifa!=0; ifa=ifa->ifa_next){
|
||||
struct sockaddr * sa;
|
||||
if (!(ifa->ifa_flags & IFF_BROADCAST))
|
||||
continue;
|
||||
|
||||
|
||||
if(!conf_use_loopback){
|
||||
if ((ifa->ifa_flags & IFF_LOOPBACK))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
sa = ifa->ifa_addr;
|
||||
if(sa->sa_family != AF_INET)
|
||||
continue;
|
||||
|
||||
char str[100];
|
||||
if (ifa->ifa_broadaddr){
|
||||
sock_addrtostr(ifa->ifa_broadaddr,str,100);
|
||||
*strchr(str,':')=0;
|
||||
stravltree_add(t,str);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
conf_bcast_addrs=malloc(t->count*sizeof(char*));
|
||||
|
||||
stravltree_foreach(t,add_bcast_addr,0,1);
|
||||
stravltree_destroy(t);
|
||||
|
||||
freeifaddrs(ifa0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int init_mcast_groups()
|
||||
{
|
||||
if (conf_mcast_groups)
|
||||
return 1;
|
||||
|
||||
int n = 0;
|
||||
int n4=0,n6=0;
|
||||
if (conf_ipv4){
|
||||
n4=sizeof(conf_default_mcast_groups_ipv4)/sizeof(char*);
|
||||
}
|
||||
|
||||
#ifdef WITH_IPV6
|
||||
if (conf_ipv6){
|
||||
n6=sizeof(conf_default_mcast_groups_ipv6)/sizeof(char*);
|
||||
}
|
||||
#endif
|
||||
n=n4+n6;
|
||||
if (n==0)
|
||||
return 1;
|
||||
|
||||
conf_mcast_groups=malloc(sizeof(char*)*n);
|
||||
if (!conf_mcast_groups)
|
||||
return 0;
|
||||
memset(conf_mcast_groups,0,n*sizeof(char*));
|
||||
|
||||
int ctr=0;
|
||||
int i;
|
||||
for(i=0; i<n4; i++){
|
||||
uint8_t *g = (uint8_t*)conf_default_mcast_groups_ipv4[i];
|
||||
conf_mcast_groups[ctr]=(char*)cw_setstr((uint8_t**)&conf_mcast_groups[ctr],g,strlen((char*)g));
|
||||
if (conf_mcast_groups[ctr])
|
||||
ctr++;
|
||||
}
|
||||
|
||||
for(i=0; i<n6; i++){
|
||||
uint8_t *g = (uint8_t*)conf_default_mcast_groups_ipv6[i];
|
||||
conf_mcast_groups[ctr]=(char*)cw_setstr((uint8_t**)&conf_mcast_groups[ctr],g,strlen((char*)g));
|
||||
if (conf_mcast_groups[ctr])
|
||||
ctr++;
|
||||
}
|
||||
|
||||
|
||||
conf_mcast_groups_len=n;
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static int conf_read_strings( cfg_t * cfg, char * name, char ***dst,int *len)
|
||||
{
|
||||
|
||||
int n,i;
|
||||
n = cfg_size(cfg, name);
|
||||
*len=n;
|
||||
if (n==0)
|
||||
return 1;
|
||||
|
||||
*dst = malloc(sizeof(char*)*n);
|
||||
if (!*dst)
|
||||
return 0;
|
||||
|
||||
for (i=0; i<n; i++) {
|
||||
char * str = cfg_getnstr(cfg,name,i);
|
||||
if (!((*dst)[i]=malloc(strlen(str)+1))) {
|
||||
*len=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy((*dst)[i],str);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int read_config(const char * filename){
|
||||
int i,n;
|
||||
|
||||
cfg_opt_t opts[] = {
|
||||
CFG_STR_LIST("listen", "{}", CFGF_NONE),
|
||||
CFG_STR_LIST("mcast_groups", "{}", CFGF_NONE),
|
||||
CFG_STR_LIST("bcast_addrs", "{}", CFGF_NONE),
|
||||
CFG_STR_LIST("ac_ips","{}",CFGF_NONE),
|
||||
CFG_SIMPLE_STR("control_port",&conf_control_port),
|
||||
CFG_SIMPLE_INT("max_wtps",&conf_max_wtps),
|
||||
CFG_SIMPLE_INT("debug_level",&conf_debug_level),
|
||||
CFG_SIMPLE_INT("vendor_id",&conf_vendor_id),
|
||||
CFG_SIMPLE_STR("ac_name",&conf_acname),
|
||||
CFG_SIMPLE_STR("ssl_cert",&conf_sslcertfilename),
|
||||
CFG_SIMPLE_STR("ssl_key",&conf_sslkeyfilename),
|
||||
CFG_SIMPLE_STR("dtls_psk",&conf_dtls_psk),
|
||||
// CFG_SIMPLE_BOOL("ignore_wtp_source_port",&conf_ignore_wtp_source_port),
|
||||
CFG_SIMPLE_BOOL("ipv4",&conf_ipv4),
|
||||
CFG_SIMPLE_BOOL("ipv6",&conf_ipv6),
|
||||
|
||||
|
||||
CFG_SIMPLE_STR("db_file",conf_db_file),
|
||||
|
||||
CFG_END()
|
||||
};
|
||||
cfg_t *cfg;
|
||||
cfg = cfg_init(opts, 0);
|
||||
|
||||
cfg_parse(cfg, filename);
|
||||
|
||||
/* read the listen addresses */
|
||||
conf_read_strings(cfg,"listen",&conf_listen_addrs,&conf_listen_addrs_len);
|
||||
|
||||
/* read multi cast groups */
|
||||
conf_read_strings(cfg,"mcast_groups",&conf_mcast_groups,&conf_mcast_groups_len);
|
||||
|
||||
/* read ipv4 broadcast addresses */
|
||||
conf_read_strings(cfg,"bcast_addrs",&conf_bcast_addrs,&conf_bcast_addrs_len);
|
||||
|
||||
|
||||
/*
|
||||
n = cfg_size(cfg, "listen");
|
||||
if (! (conf_salist = malloc(sizeof (struct sockaddr_storage)*n)) )
|
||||
return 0;
|
||||
|
||||
if (! (conf_listen_addrs=malloc(sizeof(char *)*n)))
|
||||
return 0;
|
||||
|
||||
memset(conf_listen_addrs,0,sizeof(char*)*n);
|
||||
|
||||
conf_salist_len=n;
|
||||
for (i=0; i<n; i++) {
|
||||
char * str = cfg_getnstr(cfg,"listen",i);
|
||||
if (!(conf_listen_addrs[i]=malloc(strlen(str)+1)))
|
||||
return 0;
|
||||
|
||||
strcpy(conf_listen_addrs[i],str);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* read ac_ips */
|
||||
n = cfg_size(cfg, "ac_ips");
|
||||
if (! (conf_ac_ips = malloc(sizeof (struct sockaddr)*n)) )
|
||||
return 0;
|
||||
|
||||
conf_ac_ips_len=n;
|
||||
for (i=0; i<n; i++) {
|
||||
struct sockaddr sa;
|
||||
char * str = cfg_getnstr(cfg,"ac_ips",i);
|
||||
if (sock_strtoaddr ( cfg_getnstr(cfg, "ac_ips", i),&sa))
|
||||
conf_ac_ips[i]=sa;
|
||||
else{
|
||||
perror(str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cfg_free(cfg);
|
||||
|
||||
if (!init_acname() )
|
||||
return 0;
|
||||
|
||||
if (!init_version())
|
||||
return 0;
|
||||
|
||||
if (!init_vendor_id())
|
||||
return 0;
|
||||
|
||||
if (!init_dtls())
|
||||
return 0;
|
||||
|
||||
|
||||
if (!init_control_port())
|
||||
return 0;
|
||||
|
||||
init_listen_addrs();
|
||||
init_mcast_groups();
|
||||
init_bcast_addrs();
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void free_config()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
94
src/ac/conf.h
Normal file
94
src/ac/conf.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
This file is part of ac.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CONF_H
|
||||
#define __CONF_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <confuse.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
|
||||
|
||||
#include "capwap.h"
|
||||
|
||||
#ifndef CONF_DEFAULT_ACNAME
|
||||
#define CONF_DEFAULT_ACNAME "AC"
|
||||
#endif
|
||||
|
||||
#ifndef CONF_DEFAULT_MAXWTPS
|
||||
#define CONF_DEFAULT_MAXWTPS 200
|
||||
#endif
|
||||
|
||||
#ifndef CONF_DEFAULT_LOGFILENAME
|
||||
#define CONF_DEFAULT_LOGFILENAME NULL
|
||||
#endif
|
||||
|
||||
#ifndef CONF_DEFAULT_CONFIGFILENAME
|
||||
#define CONF_DEFAULT_CONFIGFILENAME "ac.conf"
|
||||
#endif
|
||||
|
||||
#ifndef CONF_DEFAULT_VENDOR_ID
|
||||
#define CONF_DEFAULT_VENDOR_ID 11591 /* Free Software Foundation */
|
||||
#endif
|
||||
|
||||
#ifndef CONF_DEFAULT_SOFTWARE_VERSION
|
||||
#define CONF_DEFAULT_SOFTWARE_VERSION "AC-Tube 0.01"
|
||||
#endif
|
||||
|
||||
#ifndef CONF_DEFAULT_HARDWARE_VERSION
|
||||
#define CONF_DEFAULT_HARDWARE_VERSION "Linux/X86"
|
||||
#endif
|
||||
|
||||
#ifndef CONF_DEFAULT_CONTROL_PORT
|
||||
#define CONF_DEFAULT_CONTROL_PORT CAPWAP_CONTROL_PORT
|
||||
#endif
|
||||
|
||||
|
||||
extern char * conf_acname;
|
||||
extern int conf_acname_len;
|
||||
extern long conf_max_wtps;
|
||||
extern char * conf_logfilename;
|
||||
extern struct sockaddr_storage * conf_salist;
|
||||
extern int conf_salist_len;
|
||||
extern long conf_vendor_id;
|
||||
extern char * conf_hardware_version;
|
||||
extern char * conf_software_version;
|
||||
extern char ** conf_listen_addrs;
|
||||
extern int conf_listen_addrs_len;
|
||||
|
||||
extern struct sockaddr * conf_ac_ips;
|
||||
extern int conf_ac_ips_len;
|
||||
|
||||
|
||||
extern int read_config(const char * filename);
|
||||
extern cfg_bool_t conf_ignore_wtp_source_port;
|
||||
extern char * conf_control_port;
|
||||
|
||||
extern char * conf_dtls_psk;
|
||||
|
||||
extern char ** conf_mcast_groups;
|
||||
extern int conf_mcast_groups_len;
|
||||
|
||||
extern char ** conf_bcast_addrs;
|
||||
extern int conf_bcast_addrs_len;
|
||||
|
||||
extern long conf_debug_level;
|
||||
|
||||
#endif
|
35
src/ac/db.c
Normal file
35
src/ac/db.c
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
|
||||
|
||||
|
||||
void test_db()
|
||||
{
|
||||
// A prepered statement for fetching tables
|
||||
sqlite3_stmt *stmt;
|
||||
//
|
||||
// // Create a handle for database connection, create a pointer to sqlite3
|
||||
sqlite3 *handle;
|
||||
int rc = sqlite3_open("ac.sqlite3",&handle);
|
||||
|
||||
if ( rc )
|
||||
{
|
||||
perror("sqlite");
|
||||
printf("Database failed\n");
|
||||
|
||||
}
|
||||
|
||||
printf ("DB RC: %i\n",rc);
|
||||
|
||||
char cmd[100] = "xCREATE TABLE IF NOT EXISTS aclist (uname TEXT PRIMARY KEY,pass TEXT NOT NULL,activated INTEGER)";
|
||||
|
||||
rc = sqlite3_exec(handle,cmd,0,0,0);
|
||||
|
||||
printf("CT RC: %i\n",rc);
|
||||
const char *em = sqlite3_errmsg(handle);
|
||||
printf("ErrMsg: %s\n",em);
|
||||
return ;
|
||||
|
||||
|
||||
}
|
341
src/ac/socklist.c
Normal file
341
src/ac/socklist.c
Normal file
@ -0,0 +1,341 @@
|
||||
/*
|
||||
This file is part of actube.
|
||||
|
||||
actube is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
#include "cw_log.h"
|
||||
#include "sock.h"
|
||||
|
||||
|
||||
#include "socklist.h"
|
||||
|
||||
|
||||
struct socklistelem * socklist=0;
|
||||
int socklist_len;
|
||||
static pthread_mutex_t socklist_mutex;
|
||||
static int socklist_wtpcount=0;
|
||||
|
||||
|
||||
int socklist_init()
|
||||
{
|
||||
|
||||
if (pthread_mutex_init(&socklist_mutex,NULL))
|
||||
return 0;
|
||||
|
||||
|
||||
socklist = malloc(sizeof(struct socklistelem) * SOCKLIST_SIZE);
|
||||
memset(socklist,0,sizeof(struct socklistelem)*SOCKLIST_SIZE);
|
||||
if (!socklist){
|
||||
cw_log(LOG_ERR,"Fatal error while initializing socklist: %s",strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
void socklist_lock()
|
||||
{
|
||||
pthread_mutex_lock(&socklist_mutex);
|
||||
}
|
||||
|
||||
void socklist_unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&socklist_mutex);
|
||||
}
|
||||
|
||||
|
||||
void socklist_destroy()
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<socklist_len; i++){
|
||||
close(socklist[i].sockfd);
|
||||
}
|
||||
free(socklist);
|
||||
socklist=0;
|
||||
pthread_mutex_destroy(&socklist_mutex);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int find_reply_socket(struct sockaddr *sa,int bc)
|
||||
{
|
||||
int bestsockfd = -1;
|
||||
int i;
|
||||
for (i=0; i<socklist_len; i++){
|
||||
struct sockaddr_storage sn;
|
||||
memset(&sn,0,sizeof(sn));
|
||||
unsigned int snlen = sizeof(struct sockaddr_storage);
|
||||
|
||||
if (getsockname(socklist[i].sockfd,(struct sockaddr*)&sn,&snlen)<0){
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sa->sa_family!=sn.ss_family)
|
||||
continue;
|
||||
|
||||
if (bestsockfd == -1)
|
||||
bestsockfd = socklist[i].sockfd;
|
||||
|
||||
if (!bc)
|
||||
return bestsockfd;
|
||||
|
||||
struct sockaddr_storage bcaddr;
|
||||
|
||||
if (!sock_getbroadcastaddr((struct sockaddr*)&sn,(struct sockaddr*)&bcaddr))
|
||||
continue;
|
||||
|
||||
if (sock_cmpaddr((struct sockaddr*)&bcaddr,sa,0))
|
||||
continue;
|
||||
|
||||
bestsockfd = socklist[i].sockfd;
|
||||
|
||||
|
||||
}
|
||||
return bestsockfd;
|
||||
}
|
||||
|
||||
void socklist_add_connection(int index)
|
||||
{
|
||||
socklist_lock();
|
||||
socklist[index].wtpcount++;
|
||||
socklist_wtpcount++;
|
||||
socklist_unlock();
|
||||
}
|
||||
|
||||
void socklist_del_connection(int index)
|
||||
{
|
||||
socklist_lock();
|
||||
socklist[index].wtpcount--;
|
||||
socklist_wtpcount--;
|
||||
socklist_unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int socklist_add_multicast(const char * addr, const char * port)
|
||||
{
|
||||
|
||||
struct addrinfo hints;
|
||||
struct addrinfo * res,*res0;
|
||||
memset(&hints,0,sizeof(hints));
|
||||
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_flags=AI_PASSIVE;
|
||||
|
||||
int rc = getaddrinfo(addr,port,&hints,&res0);
|
||||
if (rc!=0) {
|
||||
cw_log(LOG_ERR,"Can't bind multicast address '%s': %s",addr,gai_strerror(rc));
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(res=res0; res; res=res->ai_next){
|
||||
struct sockaddr *sa = res->ai_addr;
|
||||
int sockfd = socket(res->ai_addr->sa_family, SOCK_DGRAM, 0);
|
||||
/* create socket */
|
||||
if (sockfd==-1){
|
||||
cw_log(LOG_ERR,"Can't create multicast socket: %",strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* bind address */
|
||||
if ( bind(sockfd,sa,sock_addrlen(sa)) < 0) {
|
||||
close(sockfd);
|
||||
cw_log(LOG_ERR,"Can't bind multicast %s: %s",addr,strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* use setsockopt() to request that the kernel joins a multicast group */
|
||||
void *opt;
|
||||
int optlen;
|
||||
if (res->ai_addr->sa_family == AF_INET){
|
||||
|
||||
struct ip_mreq mreq;
|
||||
memset(&mreq,0,sizeof(mreq));
|
||||
struct sockaddr_in * sain = (struct sockaddr_in*)res->ai_addr;
|
||||
mreq.imr_multiaddr.s_addr=sain->sin_addr.s_addr;
|
||||
mreq.imr_interface.s_addr=htonl(INADDR_ANY);
|
||||
opt = &mreq;
|
||||
optlen=sizeof(mreq);
|
||||
|
||||
char sinin[100];
|
||||
sock_addrtostr((struct sockaddr*)sain,sinin,100);
|
||||
|
||||
if (setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,opt,optlen) < 0) {
|
||||
close(sockfd);
|
||||
cw_log(LOG_ERR,"Can't add multicast membership %s: %s",addr,strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
if (res->ai_addr->sa_family == AF_INET6){
|
||||
struct ipv6_mreq mreq;
|
||||
memset(&mreq,0,sizeof(mreq));
|
||||
struct sockaddr_in6 * sain6 = (struct sockaddr_in6*)res->ai_addr;
|
||||
// mreq.ipv6mr_multiaddr.s_addr=sain->sin_addr.s_addr;
|
||||
memcpy(&mreq.ipv6mr_multiaddr.s6_addr,&sain6->sin6_addr.s6_addr,sizeof(sain6->sin6_addr.s6_addr));
|
||||
// int si = sizeof(sain6->sin6_addr.s6_addr);
|
||||
|
||||
// int i = sain6->sin6_addr.s6_addr;
|
||||
mreq.ipv6mr_interface=0; //htonl(INADDR_ANY);
|
||||
opt = &mreq;
|
||||
optlen=sizeof(mreq);
|
||||
if (setsockopt(sockfd,IPPROTO_IPV6,IPV6_JOIN_GROUP,opt,optlen) < 0) {
|
||||
close(sockfd);
|
||||
cw_log(LOG_ERR,"Can't join multicast group %s: %s",addr,strerror(errno));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
int rfd = find_reply_socket(sa,0);
|
||||
|
||||
socklist[socklist_len].sockfd=sockfd;
|
||||
socklist[socklist_len].reply_sockfd=rfd;
|
||||
socklist[socklist_len].type=SOCKLIST_BCASTMCAST_SOCKET;
|
||||
socklist[socklist_len].family=sa->sa_family;
|
||||
|
||||
socklist_len++;
|
||||
|
||||
cw_log(LOG_INFO,"Bound to multicast group: %s (fd=%i,r:%i)",addr,sockfd,rfd);
|
||||
}
|
||||
|
||||
freeaddrinfo(res0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int socklist_add_unicast(const char *addr, const char * port)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo * res,*res0;
|
||||
memset(&hints,0,sizeof(hints));
|
||||
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_flags=AI_PASSIVE;
|
||||
|
||||
int rc = getaddrinfo(addr,port,&hints,&res0);
|
||||
if (rc!=0) {
|
||||
cw_log(LOG_ERR,"Can't bind multicast address '%s': %s",addr,gai_strerror(rc));
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(res=res0; res; res=res->ai_next){
|
||||
struct sockaddr *sa = res->ai_addr;
|
||||
int sockfd = socket(res->ai_addr->sa_family, SOCK_DGRAM, 0);
|
||||
/* create socket */
|
||||
if (sockfd==-1){
|
||||
cw_log(LOG_ERR,"Can't create unicast socket: %",strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* bind address */
|
||||
if ( bind(sockfd,sa,sock_addrlen(sa)) < 0) {
|
||||
close(sockfd);
|
||||
cw_log(LOG_ERR,"Can't bind unicast socket %s: %s",addr,strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
socklist[socklist_len].sockfd=sockfd;
|
||||
socklist[socklist_len].reply_sockfd=sockfd;
|
||||
socklist[socklist_len].family=sa->sa_family;
|
||||
socklist[socklist_len].type=SOCKLIST_UNICAST_SOCKET;
|
||||
|
||||
socklist_len++;
|
||||
cw_log(LOG_INFO,"Bound to: %s (%i)\n",addr,sockfd);
|
||||
}
|
||||
|
||||
freeaddrinfo(res0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int socklist_add_broadcast(const char *addr, const char * port)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo * res,*res0;
|
||||
memset(&hints,0,sizeof(hints));
|
||||
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_flags=AI_PASSIVE;
|
||||
|
||||
|
||||
int rc = getaddrinfo(addr,port,&hints,&res0);
|
||||
if (rc!=0) {
|
||||
cw_log(LOG_ERR,"Can't bind broadcast address '%s': %s",addr,gai_strerror(rc));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sockfd;
|
||||
for(res=res0; res; res=res->ai_next){
|
||||
|
||||
struct sockaddr *sa = res->ai_addr;
|
||||
sockfd = socket(res->ai_addr->sa_family, SOCK_DGRAM, 0);
|
||||
|
||||
/* create socket */
|
||||
if (sockfd==-1){
|
||||
cw_log(LOG_ERR,"Can't create broadcast socket: %",strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef IP_BINDANY
|
||||
struct sockaddr_in * sain = (struct sockaddr_in*)sa;
|
||||
if (sain->sin_addr.s_addr==INADDR_BROADCAST ){
|
||||
int opt=1;
|
||||
if (setsockopt(sockfd, IPPROTO_IP, IP_BINDANY, &opt, sizeof(opt))){
|
||||
cw_log(LOG_ERR,"Can't set sockopt IP_BIND_ANY: %s",strerror(errno));
|
||||
continue;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
/* bind address */
|
||||
if ( bind(sockfd,sa,sock_addrlen(sa)) < 0) {
|
||||
close(sockfd);
|
||||
sockfd=-1;
|
||||
cw_log(LOG_ERR,"Can't bind broadcast %s: %s",addr,strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int rfd = find_reply_socket(sa,1);
|
||||
|
||||
socklist[socklist_len].sockfd=sockfd;
|
||||
socklist[socklist_len].reply_sockfd=rfd;
|
||||
socklist[socklist_len].type=SOCKLIST_BCASTMCAST_SOCKET;
|
||||
socklist[socklist_len].family=sa->sa_family;
|
||||
socklist_len++;
|
||||
|
||||
cw_log(LOG_INFO,"Bound to broadcast: %s (%i) (R:%i)\n",addr,sockfd,rfd);
|
||||
}
|
||||
|
||||
freeaddrinfo(res0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
51
src/ac/socklist.h
Normal file
51
src/ac/socklist.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
This file is part of actube.
|
||||
|
||||
actube is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __SOCKLIST_H
|
||||
#define __SOCKLIST_H
|
||||
|
||||
#define SOCKLIST_SIZE 32
|
||||
|
||||
enum {
|
||||
SOCKLIST_UNICAST_SOCKET,
|
||||
SOCKLIST_BCASTMCAST_SOCKET
|
||||
};
|
||||
|
||||
struct socklistelem{
|
||||
int sockfd;
|
||||
int reply_sockfd;
|
||||
int type;
|
||||
int family;
|
||||
int wtpcount;
|
||||
};
|
||||
|
||||
|
||||
extern int socklist_add_multicast(const char * addr, const char * port);
|
||||
extern int socklist_add_unicast(const char *addr, const char * port);
|
||||
extern int socklist_add_broadcast(const char *addr, const char * port);
|
||||
extern int socklist_init();
|
||||
extern void socklist_destroy();
|
||||
extern struct socklistelem * socklist;
|
||||
extern int socklist_len;
|
||||
extern void socklist_lock();
|
||||
extern void socklist_unlock();
|
||||
void socklist_add_connection(int index);
|
||||
void socklist_del_connection(int index);
|
||||
|
||||
|
||||
#endif
|
149
src/ac/wtplist.c
Normal file
149
src/ac/wtplist.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
This file is part of actube.
|
||||
|
||||
actube is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
|
||||
#define MAX_WTPS 200
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "wtplist.h"
|
||||
#include "conn.h"
|
||||
#include "sock.h"
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "cw_log.h"
|
||||
|
||||
/*
|
||||
static struct wtpman ** wtplist = 0;
|
||||
static pthread_mutex_t wtplist_mutex;
|
||||
|
||||
static int max_wtp_connections;
|
||||
*/
|
||||
|
||||
|
||||
static struct connlist * connlist;
|
||||
|
||||
|
||||
int wtplist_init()
|
||||
{
|
||||
|
||||
connlist = connlist_create(0);
|
||||
if (!connlist)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void wtplist_lock()
|
||||
{
|
||||
connlist_lock(connlist);
|
||||
|
||||
}
|
||||
|
||||
void wtplist_unlock()
|
||||
{
|
||||
connlist_unlock(connlist);
|
||||
}
|
||||
|
||||
|
||||
void wtplist_destroy()
|
||||
{
|
||||
connlist_destroy(connlist);
|
||||
|
||||
/* if (wtplist)
|
||||
free (wtplist);
|
||||
pthread_mutex_destroy(&wtplist_mutex);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
struct wtpman * wtplist_get(const struct sockaddr * addr)
|
||||
{
|
||||
|
||||
struct conn * conn = connlist_get(connlist,addr);
|
||||
if (!conn)
|
||||
return 0;
|
||||
return conn->data;
|
||||
|
||||
/*
|
||||
int i;
|
||||
for (i=0; i<max_wtp_connections; i++){
|
||||
if (!wtplist[i])
|
||||
continue;
|
||||
|
||||
if ( sock_cmpaddr(&wtplist[i]->conn->addr,addr,1))
|
||||
continue;
|
||||
struct wtpman * wtpman = wtplist[i];
|
||||
return wtpman;
|
||||
|
||||
}
|
||||
return NULL;
|
||||
*/
|
||||