rework socket and discovery handling
Swtich sockets to connected when talking to a specific AC. Use unconnected UDP sockets only during DISCOVERY. In JOIN, we need send our local address. The old, routing table based local address discovery is broken for many reasons (VRF, policy routing, ...). With a connected socket, we can the same information with a simple getsockname. During DISCOVERY we are talking to all potential AC's at once. So using an unconnected socket makes still sense.
This commit is contained in:
parent
067eb8d11a
commit
8dc30ae3c4
@ -143,6 +143,15 @@ int capwap_bind_sockets(struct capwap_network* net) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_connect_socket(struct capwap_network* net, union sockaddr_capwap *peeraddr)
|
||||
{
|
||||
if (net->socket < 0)
|
||||
return -1;
|
||||
|
||||
return connect(net->socket, &peeraddr->sa, sizeof(peeraddr->ss));
|
||||
}
|
||||
|
||||
/* Close socket */
|
||||
void capwap_close_sockets(struct capwap_network* net) {
|
||||
ASSERT(net != NULL);
|
||||
@ -154,6 +163,17 @@ void capwap_close_sockets(struct capwap_network* net) {
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_getsockname(struct capwap_network* net, union sockaddr_capwap *addr)
|
||||
{
|
||||
socklen_t addrlen = sizeof(addr->ss);
|
||||
|
||||
if (net->socket < 0)
|
||||
return -1;
|
||||
|
||||
return getsockname(net->socket, &addr->sa, &addrlen);
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_ipv4_mapped_ipv6(union sockaddr_capwap* addr) {
|
||||
uint32_t inetaddr;
|
||||
|
@ -56,8 +56,11 @@ int capwap_get_macaddress_from_interface(const char* interface, char* macaddress
|
||||
int capwap_network_get_localaddress(union sockaddr_capwap* localaddr, union sockaddr_capwap* peeraddr, char* iface);
|
||||
|
||||
int capwap_bind_sockets(struct capwap_network* net);
|
||||
int capwap_connect_socket(struct capwap_network* net, union sockaddr_capwap *peeraddr);
|
||||
void capwap_close_sockets(struct capwap_network* net);
|
||||
|
||||
int capwap_getsockname(struct capwap_network* net, union sockaddr_capwap *addr);
|
||||
|
||||
int capwap_ipv4_mapped_ipv6(union sockaddr_capwap* addr);
|
||||
int capwap_compare_ip(union sockaddr_capwap* addr1, union sockaddr_capwap* addr2);
|
||||
|
||||
|
@ -363,8 +363,9 @@ int wtp_dfa_running(void) {
|
||||
int check;
|
||||
|
||||
/* Check source */
|
||||
if (capwap_compare_ip(&g_wtp.dtls.peeraddr, &fromaddr)) {
|
||||
capwap_logging_debug("WTP compare failed, drop packet");
|
||||
if (g_wtp.state != CAPWAP_DISCOVERY_STATE &&
|
||||
capwap_compare_ip(&g_wtp.dtls.peeraddr, &fromaddr)) {
|
||||
capwap_logging_debug("CAPWAP packet from unknown WTP when not in DISCOVERY, drop packet");
|
||||
continue; /* Unknown source */
|
||||
}
|
||||
|
||||
|
@ -106,22 +106,30 @@ void wtp_dfa_state_discovery_timeout(struct capwap_timeout* timeout, unsigned lo
|
||||
if (peeraddr.ss.ss_family != AF_UNSPEC) {
|
||||
union sockaddr_capwap localaddr;
|
||||
|
||||
/* Retrieve local address */
|
||||
if (!capwap_network_get_localaddress(&localaddr, &peeraddr, g_wtp.net.bindiface)) {
|
||||
CAPWAP_SET_NETWORK_PORT(&localaddr, CAPWAP_GET_NETWORK_PORT(&g_wtp.net.localaddr));
|
||||
|
||||
/* */
|
||||
capwap_crypt_setconnection(&g_wtp.dtls, g_wtp.net.socket, &localaddr, &peeraddr);
|
||||
|
||||
/* */
|
||||
if (!g_wtp.enabledtls) {
|
||||
wtp_send_join(); /* Bypass DTLS connection */
|
||||
} else {
|
||||
wtp_start_dtlssetup(); /* Create DTLS connection */
|
||||
}
|
||||
|
||||
if (capwap_connect_socket(&g_wtp.net, &peeraddr) < 0) {
|
||||
capwap_logging_fatal("Cannot bind control address");
|
||||
capwap_close_sockets(&g_wtp.net);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Retrieve local address */
|
||||
if (capwap_getsockname(&g_wtp.net, &localaddr) < 0) {
|
||||
capwap_logging_fatal("Cannot get local endpoint address");
|
||||
capwap_close_sockets(&g_wtp.net);
|
||||
return;
|
||||
}
|
||||
|
||||
/* */
|
||||
capwap_crypt_setconnection(&g_wtp.dtls, g_wtp.net.socket, &localaddr, &peeraddr);
|
||||
|
||||
/* */
|
||||
if (!g_wtp.enabledtls) {
|
||||
wtp_send_join(); /* Bypass DTLS connection */
|
||||
} else {
|
||||
wtp_start_dtlssetup(); /* Create DTLS connection */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,6 +144,12 @@ void wtp_dfa_state_discovery_timeout(struct capwap_timeout* timeout, unsigned lo
|
||||
struct capwap_header_data capwapheader;
|
||||
struct capwap_packet_txmng* txmngpacket;
|
||||
|
||||
if (g_wtp.net.socket < 0)
|
||||
if (capwap_bind_sockets(&g_wtp.net) < 0) {
|
||||
capwap_logging_fatal("Cannot bind control address");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Update status radio */
|
||||
g_wtp.descriptor.radiosinuse = wtp_update_radio_in_use();
|
||||
|
||||
@ -184,7 +198,8 @@ void wtp_dfa_state_discovery_timeout(struct capwap_timeout* timeout, unsigned lo
|
||||
}
|
||||
|
||||
/* */
|
||||
void wtp_dfa_state_discovery(struct capwap_parsed_packet* packet) {
|
||||
void wtp_dfa_state_discovery(struct capwap_parsed_packet* packet)
|
||||
{
|
||||
unsigned short binding;
|
||||
struct capwap_array* controlip;
|
||||
|
||||
@ -192,7 +207,10 @@ void wtp_dfa_state_discovery(struct capwap_parsed_packet* packet) {
|
||||
|
||||
/* */
|
||||
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
|
||||
if ((binding == g_wtp.binding) && (packet->rxmngpacket->ctrlmsg.type == CAPWAP_DISCOVERY_RESPONSE) && (g_wtp.localseqnumber == packet->rxmngpacket->ctrlmsg.seq)) {
|
||||
if ((binding == g_wtp.binding) &&
|
||||
(packet->rxmngpacket->ctrlmsg.type == CAPWAP_DISCOVERY_RESPONSE) &&
|
||||
(g_wtp.localseqnumber == packet->rxmngpacket->ctrlmsg.seq))
|
||||
{
|
||||
struct capwap_resultcode_element* resultcode;
|
||||
|
||||
/* */
|
||||
|
@ -2,6 +2,61 @@
|
||||
#include "capwap_dfa.h"
|
||||
#include "wtp_dfa.h"
|
||||
|
||||
static int wtp_join_prefered_ac()
|
||||
{
|
||||
if (g_wtp.acdiscoveryrequest ||
|
||||
g_wtp.acpreferedarray->count == 0)
|
||||
/* goto discovery */
|
||||
return -1;
|
||||
|
||||
while (g_wtp.acpreferedselected < g_wtp.acpreferedarray->count)
|
||||
{
|
||||
union sockaddr_capwap localaddr;
|
||||
union sockaddr_capwap *peeraddr;
|
||||
|
||||
/* Found in configuration file the AC address */
|
||||
peeraddr = capwap_array_get_item_pointer(g_wtp.acpreferedarray,
|
||||
g_wtp.acpreferedselected);
|
||||
|
||||
/* Next AC */
|
||||
g_wtp.acpreferedselected++;
|
||||
|
||||
/* restart and connect the control Socket */
|
||||
capwap_close_sockets(&g_wtp.net);
|
||||
if (capwap_bind_sockets(&g_wtp.net) < 0) {
|
||||
capwap_logging_fatal("Cannot bind control address");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (capwap_connect_socket(&g_wtp.net, peeraddr) < 0) {
|
||||
capwap_logging_fatal("Cannot bind control address");
|
||||
capwap_close_sockets(&g_wtp.net);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Retrieve local address */
|
||||
if (capwap_getsockname(&g_wtp.net, &localaddr) < 0) {
|
||||
capwap_logging_fatal("Cannot get local endpoint address");
|
||||
capwap_close_sockets(&g_wtp.net);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
capwap_crypt_setconnection(&g_wtp.dtls, g_wtp.net.socket, &localaddr, peeraddr);
|
||||
|
||||
/* */
|
||||
if (!g_wtp.enabledtls) {
|
||||
wtp_send_join(); /* Bypass DTLS connection */
|
||||
} else {
|
||||
wtp_start_dtlssetup(); /* Create DTLS connection */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void wtp_dfa_state_idle(void) {
|
||||
long discoveryinterval;
|
||||
@ -10,36 +65,14 @@ void wtp_dfa_state_idle(void) {
|
||||
g_wtp.teardown = 0;
|
||||
capwap_timeout_unsetall(g_wtp.timeout);
|
||||
|
||||
/* */
|
||||
if (!g_wtp.acdiscoveryrequest && (g_wtp.acpreferedarray->count > 0)) {
|
||||
while (g_wtp.acpreferedselected < g_wtp.acpreferedarray->count) {
|
||||
union sockaddr_capwap localaddr;
|
||||
union sockaddr_capwap peeraddr;
|
||||
if (wtp_join_prefered_ac() == 0)
|
||||
return;
|
||||
|
||||
/* Found in configuration file the AC address */
|
||||
memcpy(&peeraddr, capwap_array_get_item_pointer(g_wtp.acpreferedarray, g_wtp.acpreferedselected), sizeof(union sockaddr_capwap));
|
||||
|
||||
/* Next AC */
|
||||
g_wtp.acpreferedselected++;
|
||||
|
||||
/* Retrieve local address */
|
||||
if (!capwap_network_get_localaddress(&localaddr, &peeraddr, g_wtp.net.bindiface)) {
|
||||
CAPWAP_SET_NETWORK_PORT(&localaddr, CAPWAP_GET_NETWORK_PORT(&g_wtp.net.localaddr));
|
||||
|
||||
/* */
|
||||
capwap_crypt_setconnection(&g_wtp.dtls, g_wtp.net.socket, &localaddr, &peeraddr);
|
||||
|
||||
/* */
|
||||
if (!g_wtp.enabledtls) {
|
||||
wtp_send_join(); /* Bypass DTLS connection */
|
||||
} else {
|
||||
wtp_start_dtlssetup(); /* Create DTLS connection */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (g_wtp.net.socket < 0)
|
||||
if (capwap_bind_sockets(&g_wtp.net) < 0) {
|
||||
capwap_logging_fatal("Cannot bind control address");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Discovery AC */
|
||||
g_wtp.acpreferedselected = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user