2014-07-11 22:12:11 +02:00
|
|
|
/*
|
2014-07-18 19:02:47 +02:00
|
|
|
This file is part of AC-Tube.
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2014-07-18 19:02:47 +02:00
|
|
|
AC-Tube is free software: you can redistribute it and/or modify
|
2014-07-11 22:12:11 +02:00
|
|
|
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.
|
|
|
|
|
2014-07-18 19:02:47 +02:00
|
|
|
AC-Tube is distributed in the hope that it will be useful,
|
2014-07-11 22:12:11 +02:00
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
|
|
|
2016-03-03 19:51:42 +01:00
|
|
|
#include "cw/capwap.h"
|
|
|
|
#include "cw/capwap_items.h"
|
|
|
|
#include "cw/log.h"
|
|
|
|
#include "cw/sock.h"
|
|
|
|
#include "cw/cw_util.h"
|
|
|
|
#include "cw/aciplist.h"
|
|
|
|
#include "cw/acpriolist.h"
|
|
|
|
#include "cw/timer.h"
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2015-04-07 07:42:36 +02:00
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
#include "wtp.h"
|
|
|
|
#include "wtp_conf.h"
|
|
|
|
#include "wtp_interface.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-03-06 13:34:34 +01:00
|
|
|
cw_aciplist_t cw_select_ac(struct conn *conn, mbag_t discs)
|
2015-04-10 17:14:55 +02:00
|
|
|
{
|
2016-03-05 08:52:22 +01:00
|
|
|
|
2016-03-05 08:05:46 +01:00
|
|
|
/* create a list for results */
|
|
|
|
cw_aciplist_t resultlist=cw_aciplist_create();
|
|
|
|
if (!resultlist)
|
|
|
|
return NULL;
|
2016-03-06 13:34:34 +01:00
|
|
|
if (!discs)
|
2016-03-05 08:05:46 +01:00
|
|
|
return resultlist;
|
|
|
|
|
2016-03-06 13:34:34 +01:00
|
|
|
/*
|
2015-04-10 17:14:55 +02:00
|
|
|
cw_aciplist_t aciplist = cw_aciplist_create();
|
|
|
|
if (!aciplist) {
|
|
|
|
cw_log(LOG_ERROR, "Can't allocate aciplist");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-03-06 13:34:34 +01:00
|
|
|
*/
|
2015-05-04 07:47:15 +02:00
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
/* get the AC Name with Priority list */
|
|
|
|
cw_acpriolist_t priolist;
|
2015-05-01 00:16:54 +02:00
|
|
|
priolist = mbag_get_mavl(conn->config, CW_ITEM_AC_NAME_WITH_PRIORITY);
|
2016-03-06 13:34:34 +01:00
|
|
|
if (!priolist )
|
2015-05-04 07:47:15 +02:00
|
|
|
priolist=cw_acpriolist_create();
|
2015-04-10 17:14:55 +02:00
|
|
|
|
|
|
|
|
2016-03-06 13:34:34 +01:00
|
|
|
/* for each discovery reponse */
|
|
|
|
DEFINE_AVLITER(i, discs);
|
2015-04-10 17:14:55 +02:00
|
|
|
avliter_foreach(&i){
|
2016-03-06 11:23:50 +01:00
|
|
|
|
2015-04-19 23:27:44 +02:00
|
|
|
mbag_t ac = ((mbag_item_t *) (avliter_get(&i)))->data;
|
2015-04-10 17:14:55 +02:00
|
|
|
|
2016-03-06 13:34:34 +01:00
|
|
|
/* get the ac name */
|
2015-04-19 23:27:44 +02:00
|
|
|
char *ac_name = mbag_get_str(ac, CW_ITEM_AC_NAME,NULL);
|
2015-04-10 17:14:55 +02:00
|
|
|
int prio = 256;
|
2016-03-06 13:34:34 +01:00
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
if (ac_name) {
|
|
|
|
/* See if we can find AC Name in Priority List */
|
|
|
|
if (priolist)
|
|
|
|
prio = cw_acpriolist_get(priolist, ac_name);
|
|
|
|
}
|
|
|
|
|
2016-03-06 13:34:34 +01:00
|
|
|
/* get the IP list, the current AC has sent */
|
2015-04-10 17:14:55 +02:00
|
|
|
cw_aciplist_t acips =
|
2015-05-01 00:16:54 +02:00
|
|
|
mbag_get_mavl(ac, CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST);
|
2015-04-10 17:14:55 +02:00
|
|
|
|
2016-03-28 10:50:58 +02:00
|
|
|
if (!acips)
|
|
|
|
continue;
|
|
|
|
|
2016-03-06 13:34:34 +01:00
|
|
|
/* for each IP from the current AC add it to the result list
|
|
|
|
* and give it the priority whe have determined */
|
2015-04-10 17:14:55 +02:00
|
|
|
DEFINE_AVLITER(i2, acips);
|
|
|
|
avliter_foreach(&i2){
|
2016-03-06 11:23:50 +01:00
|
|
|
|
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
cw_acip_t *acip = avliter_get(&i2);
|
2016-03-06 11:23:50 +01:00
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
cw_acip_t *n = malloc(sizeof(cw_acip_t));
|
|
|
|
memcpy(n,acip,sizeof(cw_acip_t));
|
2016-03-06 13:34:34 +01:00
|
|
|
|
|
|
|
/* we missuse the wtp_count to sort by
|
|
|
|
* priority and wp_count */
|
2015-04-10 17:14:55 +02:00
|
|
|
n->wtp_count |= prio<<16;
|
2016-03-06 13:34:34 +01:00
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
cw_aciplist_del(resultlist,n);
|
|
|
|
cw_aciplist_add(resultlist,n);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return resultlist;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-04-07 07:42:36 +02:00
|
|
|
static int run_discovery(struct conn *conn)
|
2014-07-11 22:12:11 +02:00
|
|
|
{
|
2015-04-19 23:27:44 +02:00
|
|
|
// conn->incomming = mbag_create();
|
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
|
|
|
|
conn->capwap_state = CW_STATE_DISCOVERY;
|
2015-04-19 23:27:44 +02:00
|
|
|
mbag_set_byte(conn->outgoing, CW_ITEM_DISCOVERY_TYPE,
|
2015-04-10 17:14:55 +02:00
|
|
|
CW_DISCOVERY_TYPE_UNKNOWN);
|
|
|
|
|
2015-03-15 09:18:49 +01:00
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
cw_init_request(conn, CW_MSG_DISCOVERY_REQUEST);
|
|
|
|
cw_put_msg(conn, conn->req_buffer);
|
|
|
|
conn_send_msg(conn, conn->req_buffer);
|
2015-03-15 09:18:49 +01:00
|
|
|
|
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
time_t timer = cw_timer_start(0);
|
2015-03-15 09:18:49 +01:00
|
|
|
|
2014-07-28 07:08:27 +02:00
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
while (!cw_timer_timeout(timer)
|
|
|
|
&& conn->capwap_state == CW_STATE_DISCOVERY) {
|
2015-04-19 23:27:44 +02:00
|
|
|
mavl_del_all(conn->incomming);
|
2015-04-10 17:14:55 +02:00
|
|
|
|
2015-04-12 23:28:55 +02:00
|
|
|
int rc = cw_read_from(conn);
|
2015-04-10 17:14:55 +02:00
|
|
|
|
|
|
|
if (rc<0) {
|
|
|
|
if (errno==EAGAIN)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
cw_log(LOG_ERROR,"Error reading messages: %s",strerror(errno));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-03-15 09:18:49 +01:00
|
|
|
|
2015-04-20 02:26:24 +02:00
|
|
|
|
2015-04-19 23:27:44 +02:00
|
|
|
mbag_t discs;
|
2015-05-01 00:16:54 +02:00
|
|
|
discs = mbag_get_mavl(conn->remote, CW_ITEM_DISCOVERIES);
|
2015-04-20 02:26:24 +02:00
|
|
|
|
2015-04-10 21:44:05 +02:00
|
|
|
|
|
|
|
if (!discs) {
|
|
|
|
cw_log(LOG_ERR,"No discovery responses received");
|
|
|
|
return 0;
|
|
|
|
}
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
cw_aciplist_t list = cw_select_ac(conn, discs);
|
|
|
|
|
2015-04-19 23:27:44 +02:00
|
|
|
|
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
DEFINE_AVLITER(ii,list);
|
|
|
|
avliter_foreach(&ii){
|
|
|
|
cw_acip_t * ip = avliter_get(&ii);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-04-19 23:27:44 +02:00
|
|
|
|
|
|
|
|
2015-04-20 02:26:24 +02:00
|
|
|
mavl_del_all(conn->remote);
|
2015-04-10 17:14:55 +02:00
|
|
|
|
2015-05-01 00:16:54 +02:00
|
|
|
mbag_set_mavl(conn->local,CW_ITEM_CAPWAP_CONTROL_IP_ADDRESS_LIST,list);
|
2015-04-10 17:14:55 +02:00
|
|
|
|
2015-04-26 12:36:53 +02:00
|
|
|
return 1;
|
2014-07-11 22:12:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-04-07 07:42:36 +02:00
|
|
|
/**
|
|
|
|
* Run discovery for on address (eg broadcast 255.255.255.255)
|
2015-04-10 17:14:55 +02:00
|
|
|
*/
|
2015-04-07 07:42:36 +02:00
|
|
|
static int cw_run_discovery(struct conn *conn, const char *acaddr)
|
2014-07-11 22:12:11 +02:00
|
|
|
{
|
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
/* get addr of destination */
|
2014-07-11 22:12:11 +02:00
|
|
|
struct addrinfo hints;
|
2015-04-10 17:14:55 +02:00
|
|
|
struct addrinfo *res, *res0;
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
hints.ai_socktype = SOCK_DGRAM;
|
|
|
|
hints.ai_family = PF_UNSPEC;
|
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
int rc = getaddrinfo(acaddr, conf_control_port, &hints, &res0);
|
|
|
|
if (rc) {
|
|
|
|
cw_log(LOG_ERR, "Can't connect to AC %s: %s", acaddr, gai_strerror(rc));
|
2014-07-11 22:12:11 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
for (res = res0; res; res = res->ai_next) {
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
int sockfd;
|
|
|
|
int opt;
|
2015-04-10 17:14:55 +02:00
|
|
|
sockfd = socket(res->ai_family, SOCK_DGRAM, 0);
|
|
|
|
if (sockfd == -1) {
|
|
|
|
cw_log(LOG_ERR, "Can't create socket for %s: %s", acaddr,
|
|
|
|
strerror(errno));
|
2014-07-11 22:12:11 +02:00
|
|
|
continue;
|
|
|
|
}
|
2015-04-10 17:14:55 +02:00
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
opt = 1;
|
2015-04-10 17:14:55 +02:00
|
|
|
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) < 0) {
|
|
|
|
cw_log(LOG_ERR, "Can't set broadcast sockopt");
|
2014-07-11 22:12:11 +02:00
|
|
|
}
|
2015-04-10 17:14:55 +02:00
|
|
|
sock_set_recvtimeout(sockfd, 1);
|
|
|
|
sock_set_dontfrag(sockfd, 0);
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
sock_copyaddr(&conn->addr, res->ai_addr);
|
2016-03-31 07:49:06 +02:00
|
|
|
|
|
|
|
|
|
|
|
if (conf_ip){
|
|
|
|
struct sockaddr bind_address;
|
|
|
|
sock_strtoaddr(conf_ip,&bind_address);
|
|
|
|
int brc = bind(sockfd,&bind_address,sock_addrlen(&bind_address));
|
|
|
|
if (brc<0) {
|
|
|
|
cw_log(LOG_ERR,"Can't bind to %s",sock_addr2str(&bind_address));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
conn->sock = sockfd;
|
2015-04-12 23:28:55 +02:00
|
|
|
conn->readfrom = conn_recvfrom_packet;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2015-04-07 07:42:36 +02:00
|
|
|
run_discovery(conn);
|
2015-03-23 07:48:27 +01:00
|
|
|
|
2015-04-12 23:28:55 +02:00
|
|
|
conn->readfrom=NULL;
|
2015-03-23 07:48:27 +01:00
|
|
|
close(sockfd);
|
2015-04-07 07:42:36 +02:00
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
freeaddrinfo(res0);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-07 07:42:36 +02:00
|
|
|
int discovery()
|
|
|
|
{
|
2015-04-10 17:14:55 +02:00
|
|
|
struct conn *conn = get_conn();
|
2016-03-11 22:23:00 +01:00
|
|
|
|
2016-03-13 18:55:42 +01:00
|
|
|
printf("Radios = %d\n",conn->radios->count);
|
2016-03-11 22:23:00 +01:00
|
|
|
|
2015-04-10 17:14:55 +02:00
|
|
|
cw_run_discovery(conn, "255.255.255.255");
|
|
|
|
conn->capwap_state=CW_STATE_JOIN;
|
2015-04-26 12:36:53 +02:00
|
|
|
return 1;
|
2015-04-07 07:42:36 +02:00
|
|
|
}
|