2014-07-11 22:12:11 +02:00
|
|
|
/*
|
|
|
|
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/>.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2015-03-30 07:56:42 +02:00
|
|
|
#include <stdlib.h>
|
2014-07-11 22:12:11 +02:00
|
|
|
#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"
|
2015-04-07 07:42:36 +02:00
|
|
|
#include "capwap/dtls.h"
|
|
|
|
#include "capwap/cw_log.h"
|
2014-07-11 22:12:11 +02:00
|
|
|
#include "conf.h"
|
2015-04-07 07:42:36 +02:00
|
|
|
#include "capwap/sock.h"
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
#include "socklist.h"
|
|
|
|
|
2014-08-25 22:38:52 +02:00
|
|
|
#include "db.h"
|
2015-04-07 07:42:36 +02:00
|
|
|
#include "capwap/capwap_items.h"
|
|
|
|
#include "capwap/capwap_cisco.h"
|
2015-03-30 07:56:42 +02:00
|
|
|
|
2015-04-05 02:07:59 +02:00
|
|
|
#include "ac.h"
|
2015-04-07 07:42:36 +02:00
|
|
|
#include "capwap/format.h"
|
2015-03-30 07:56:42 +02:00
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
int ac_run();
|
|
|
|
|
2014-08-25 22:38:52 +02:00
|
|
|
void alive_thread(void *data)
|
|
|
|
{
|
|
|
|
while(1){
|
|
|
|
sleep(5);
|
|
|
|
db_ping();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-07 07:42:36 +02:00
|
|
|
#include "capwap/action.h"
|
2015-03-30 07:56:42 +02:00
|
|
|
|
2015-03-31 08:04:03 +02:00
|
|
|
|
2015-03-31 14:03:21 +02:00
|
|
|
/*
|
2015-03-31 08:04:03 +02:00
|
|
|
int readelem_vendor_specific_payload(struct conn *conn,struct cw_action * a,uint8_t *data,int len)
|
|
|
|
{
|
|
|
|
cw_action_t as,*af;
|
|
|
|
as = *a;
|
|
|
|
|
|
|
|
as.vendor_id = cw_get_dword(data);
|
|
|
|
as.elem_id = cw_get_word(data+4);
|
|
|
|
printf("Vendor Specific: %d, %d\n",as.vendor_id,as.elem_id);
|
|
|
|
|
|
|
|
af = cw_actionlist_get(conn->msgtr,&as);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!af) {
|
|
|
|
printf("Msg unknown\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("Found\n");
|
|
|
|
|
|
|
|
if (af->start) {
|
|
|
|
af->start(conn,af,data+6,len-6);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
2015-03-30 07:56:42 +02:00
|
|
|
}
|
2015-03-31 14:03:21 +02:00
|
|
|
*/
|
|
|
|
|
2015-03-30 07:56:42 +02:00
|
|
|
|
2015-04-05 02:07:59 +02:00
|
|
|
/*
|
2015-03-31 08:04:03 +02:00
|
|
|
int readelem_cisco_rad_name(struct conn *conn,struct cw_action * a,uint8_t *data,int len)
|
|
|
|
{
|
|
|
|
printf("Here is the rad name reader\n");
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=0; i<len; i++) {
|
|
|
|
printf("%c",data[i]);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
2015-04-05 02:07:59 +02:00
|
|
|
*/
|
2015-03-31 08:04:03 +02:00
|
|
|
|
|
|
|
|
2015-04-07 07:42:36 +02:00
|
|
|
#include "capwap/capwap_crypto.h"
|
2014-08-25 22:38:52 +02:00
|
|
|
|
2015-03-30 07:56:42 +02:00
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2015-04-07 07:42:36 +02:00
|
|
|
int main (int argc, const char * argv[])
|
|
|
|
{
|
2014-07-26 20:29:30 +02:00
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
cw_log_name="AC-Tube";
|
|
|
|
|
|
|
|
read_config("ac.conf");
|
2014-08-16 10:13:11 +02:00
|
|
|
|
2014-07-13 19:18:56 +02:00
|
|
|
|
2014-08-17 18:46:58 +02:00
|
|
|
|
2015-04-05 02:07:59 +02:00
|
|
|
|
|
|
|
cw_log(LOG_INFO,"Starting AC-Tube, Name=%s, ID=%s",conf_acname,conf_acid);
|
2014-08-17 18:46:58 +02:00
|
|
|
|
2014-08-16 10:13:11 +02:00
|
|
|
cw_dbg_opt_detail=DBG_DETAIL_ASC_DMP;
|
|
|
|
|
2015-04-05 20:27:17 +02:00
|
|
|
cw_register_actions_cipwap_ac(&capwap_actions);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
struct avltree *avlt = capwap_actions.strelem;
|
|
|
|
|
|
|
|
avltree_foreach_asc(avlt,avlprint,0);
|
|
|
|
|
|
|
|
exit(0);
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-04-05 02:07:59 +02:00
|
|
|
ac_global_init();
|
2014-08-16 10:13:11 +02:00
|
|
|
|
2015-04-05 02:07:59 +02:00
|
|
|
/*
|
2014-07-13 19:18:56 +02:00
|
|
|
db_init();
|
2014-07-15 07:33:17 +02:00
|
|
|
db_start();
|
2014-07-15 00:34:41 +02:00
|
|
|
db_ping();
|
2014-08-25 22:38:52 +02:00
|
|
|
pthread_t alth;
|
|
|
|
pthread_create (&alth, NULL, alive_thread, (void *)0);
|
2015-04-05 02:07:59 +02:00
|
|
|
*/
|
|
|
|
int rc=0;
|
2014-07-11 22:12:11 +02:00
|
|
|
dtls_init();
|
|
|
|
if (!socklist_init())
|
|
|
|
goto errX;
|
|
|
|
|
|
|
|
if (!wtplist_init())
|
|
|
|
goto errX;
|
|
|
|
|
|
|
|
|
2015-04-05 02:07:59 +02:00
|
|
|
rc = ac_run();
|
2014-07-11 22:12:11 +02:00
|
|
|
errX:
|
|
|
|
wtplist_destroy();
|
|
|
|
socklist_destroy();
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2015-04-05 02:07:59 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
void process_ctrl_packet(int index, struct sockaddr * addr, uint8_t * buffer, int len);
|
2014-07-26 20:29:30 +02:00
|
|
|
#define AC_PROTO_CAPWAP 0
|
|
|
|
#define AC_PROTO_LWAPP 1
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
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++){
|
2014-07-26 20:29:30 +02:00
|
|
|
socklist_add_unicast(conf_listen_addrs[i],conf_control_port,AC_PROTO_CAPWAP);
|
|
|
|
#ifdef WITH_LWAPP
|
|
|
|
if (conf_lwapp)
|
|
|
|
socklist_add_unicast(conf_listen_addrs[i],conf_lw_control_port,AC_PROTO_LWAPP);
|
|
|
|
#endif
|
2014-07-11 22:12:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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++){
|
2014-07-26 20:29:30 +02:00
|
|
|
socklist_add_multicast(conf_mcast_groups[i],conf_control_port,AC_PROTO_CAPWAP);
|
|
|
|
#ifdef WITH_LWAPP
|
|
|
|
if (conf_lwapp)
|
|
|
|
socklist_add_multicast(conf_mcast_groups[i],conf_lw_control_port,AC_PROTO_LWAPP);
|
|
|
|
#endif
|
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* broadcast sockety ipv4 only */
|
|
|
|
for (i=0; i<conf_bcast_addrs_len;i++){
|
2014-07-26 20:29:30 +02:00
|
|
|
socklist_add_broadcast(conf_bcast_addrs[i],conf_control_port,AC_PROTO_CAPWAP);
|
|
|
|
#ifdef WITH_LWAPP
|
2014-08-02 18:48:13 +02:00
|
|
|
// printf("Adding %d\n",socklist_len);
|
2014-07-26 20:29:30 +02:00
|
|
|
if (conf_lwapp)
|
|
|
|
socklist_add_broadcast(conf_bcast_addrs[i],conf_lw_control_port,AC_PROTO_LWAPP);
|
2014-08-02 18:48:13 +02:00
|
|
|
// printf ("SI %d, PROTO: %d\n",socklist_len-1,socklist[socklist_len-1].ac_proto);
|
2014-07-26 20:29:30 +02:00
|
|
|
#endif
|
2014-07-11 22:12:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-04-05 02:07:59 +02:00
|
|
|
//get_acinfo();
|
2014-07-28 07:07:43 +02:00
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-26 20:29:30 +02:00
|
|
|
void process_cw_ctrl_packet(int index,struct sockaddr * addr, uint8_t * buffer, int len)
|
2014-07-11 22:12:11 +02:00
|
|
|
{
|
2015-02-07 10:57:58 +01:00
|
|
|
|
2015-04-05 02:07:59 +02:00
|
|
|
// int sock = socklist[index].reply_sockfd;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2014-07-29 19:30:49 +02:00
|
|
|
char hdrstr[1024];
|
|
|
|
hdr_print(hdrstr,buffer,len);
|
2015-02-07 10:57:58 +01:00
|
|
|
cw_dbg(DBG_CW_PKT_IN,"Header for packet from %s\n%s",sock_addr2str(addr),hdrstr);
|
2014-07-29 19:30:49 +02:00
|
|
|
|
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
/* first of all check preamble */
|
2015-03-23 07:48:27 +01:00
|
|
|
int preamble = cw_get_hdr_preamble(buffer);
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
#ifdef WITH_DTLS
|
|
|
|
if (preamble != CAPWAP_PACKET_PREAMBLE && preamble != CAPWAP_DTLS_PACKET_PREAMBLE){
|
|
|
|
#else
|
|
|
|
if (preamble != CAPWAP_PACKET_PREAMBLE ){
|
|
|
|
#endif
|
2015-02-07 10:57:58 +01:00
|
|
|
cw_dbg(DBG_CW_PKT_ERR,"Discarding packet, wrong preamble, preamble = 0x%01X",preamble);
|
2014-07-11 22:12:11 +02:00
|
|
|
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);
|
|
|
|
}
|
2014-07-28 07:07:43 +02:00
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
wtpman_addpacket(wtpman,buffer,len);
|
|
|
|
wtplist_unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-26 20:29:30 +02:00
|
|
|
void process_lw_ctrl_packet(int index,struct sockaddr * addr, uint8_t * buffer, int len)
|
|
|
|
{
|
2015-04-05 02:07:59 +02:00
|
|
|
//int sock = socklist[index].reply_sockfd;
|
2014-07-26 20:29:30 +02:00
|
|
|
|
|
|
|
uint8_t * m = buffer+6;
|
|
|
|
uint32_t val = ntohl(*((uint32_t*)(m)));
|
|
|
|
|
|
|
|
|
|
|
|
printf ("VAL: %08X\n",val);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* first of all check preamble */
|
|
|
|
int version = LWTH_GET_VERSION(m);
|
|
|
|
|
|
|
|
if (version != LW_VERSION){
|
2015-02-07 11:51:29 +01:00
|
|
|
// cw_log_debug1("Discarding LWAPP packet, wrong verson");
|
2014-07-26 20:29:30 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l = LWTH_GET_LENGTH(m);
|
|
|
|
printf ("LEN = %d\n",l);
|
|
|
|
|
|
|
|
if (l+12 != len){
|
2015-02-07 11:51:29 +01:00
|
|
|
// cw_log_debug1("Discarding LWAPP packet, wrong length");
|
2014-07-26 20:29:30 +02:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2015-04-05 02:07:59 +02:00
|
|
|
//wtpman_lw_start(wtpman);
|
2014-07-26 20:29:30 +02:00
|
|
|
}
|
|
|
|
|
2015-04-05 02:07:59 +02:00
|
|
|
//wtpman_lw_addpacket(wtpman,buffer,len);
|
2014-07-26 20:29:30 +02:00
|
|
|
wtplist_unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void process_ctrl_packet(int index,struct sockaddr * addr, uint8_t * buffer, int len)
|
|
|
|
{
|
|
|
|
|
|
|
|
#ifdef WITH_CW_LOG_DEBUG
|
|
|
|
char str[100];
|
|
|
|
sock_addrtostr(addr,str,100);
|
2015-02-07 11:51:29 +01:00
|
|
|
cw_dbg(DBG_CW_PKT_IN,"Received packet from %s, len = %i, via %s\n",sock_addr2str(addr),len,
|
2014-07-26 20:29:30 +02:00
|
|
|
socklist[index].type==SOCKLIST_UNICAST_SOCKET ? "unicast":"bcast/mcast");
|
2015-02-07 11:51:29 +01:00
|
|
|
|
|
|
|
cw_dbg_dmp(DBG_CW_PKT_DMP,buffer,len,"Dump ...");
|
|
|
|
// cw_dbg_dmp(buffer,len,"Packet data for packet, recevied from %s",str);
|
2014-07-26 20:29:30 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
switch (socklist[index].ac_proto){
|
|
|
|
case AC_PROTO_CAPWAP:
|
|
|
|
process_cw_ctrl_packet(index,addr,buffer,len);
|
|
|
|
return;
|
|
|
|
case AC_PROTO_LWAPP:
|
|
|
|
process_lw_ctrl_packet(index,addr,buffer,len);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|