FossilOrigin-Name: c53d95729c009f8f80a7d63847cef7668ff73f8af0523ab65f7734696f85399cbsdmakefiles
parent
3234327f71
commit
2bae9358d7
@ -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) |
@ -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 |
@ -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; |
||||
} |
||||
|
@ -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(); |
||||
} |
||||
|
||||
|
||||
|
@ -0,0 +1,2 @@ |
||||
|
||||
#define AC_MAX_LISTEN_SOCKETS 32 |
@ -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() |
||||
{ |
||||
|
||||
} |
||||
|
||||
|
@ -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 |
@ -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 ; |
||||
|
||||
|
||||
} |
@ -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;
|
||||
} |
||||
|
||||
|
@ -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 |
||||