The capwap data channel migrated from userspace to kernalspace

This commit is contained in:
vemax78
2014-09-10 21:58:23 +02:00
parent 71006a9121
commit 8d9985fdea
104 changed files with 6967 additions and 4840 deletions

View File

@ -104,7 +104,7 @@ void ac_msgqueue_notify_closethread(pthread_t threadid) {
}
/* */
static int ac_recvfrom(struct ac_fds* fds, void* buffer, int* size, struct sockaddr_storage* recvfromaddr, struct sockaddr_storage* recvtoaddr) {
static int ac_recvfrom(struct ac_fds* fds, void* buffer, int* size, union sockaddr_capwap* fromaddr, union sockaddr_capwap* toaddr) {
int index;
ASSERT(fds);
@ -113,8 +113,7 @@ static int ac_recvfrom(struct ac_fds* fds, void* buffer, int* size, struct socka
ASSERT(buffer != NULL);
ASSERT(size != NULL);
ASSERT(*size > 0);
ASSERT(recvfromaddr != NULL);
ASSERT(recvtoaddr != NULL);
ASSERT(fromaddr != NULL);
/* Wait packet */
index = capwap_wait_recvready(fds->fdspoll, fds->fdstotalcount, NULL);
@ -146,7 +145,7 @@ static int ac_recvfrom(struct ac_fds* fds, void* buffer, int* size, struct socka
}
/* Receive packet */
if (!capwap_recvfrom_fd(fds->fdspoll[index].fd, buffer, size, recvfromaddr, recvtoaddr)) {
if (capwap_recvfrom(fds->fdspoll[index].fd, buffer, size, fromaddr, toaddr)) {
return CAPWAP_RECV_ERROR_SOCKET;
}
@ -175,28 +174,6 @@ static void ac_session_add_packet(struct ac_session_t* session, char* buffer, in
capwap_lock_exit(&session->sessionlock);
}
/* Add packet to session data */
static void ac_session_data_add_packet(struct ac_session_data_t* sessiondata, char* buffer, int size, int plainbuffer) {
struct capwap_list_item* item;
struct ac_packet* packet;
ASSERT(sessiondata != NULL);
ASSERT(buffer != NULL);
ASSERT(size > 0);
/* Copy packet */
item = capwap_itemlist_create(sizeof(struct ac_packet) + size);
packet = (struct ac_packet*)item->item;
packet->plainbuffer = plainbuffer;
memcpy(packet->buffer, buffer, size);
/* Append to packets list */
capwap_lock_enter(&sessiondata->sessionlock);
capwap_itemlist_insert_after(sessiondata->packets, NULL, item);
capwap_event_signal(&sessiondata->waitpacket);
capwap_lock_exit(&sessiondata->sessionlock);
}
/* Add action to session */
void ac_session_send_action(struct ac_session_t* session, long action, long param, const void* data, long length) {
struct capwap_list_item* item;
@ -239,52 +216,8 @@ void ac_session_send_action(struct ac_session_t* session, long action, long para
capwap_rwlock_exit(&g_ac.sessionslock);
}
/* Add action to session data */
void ac_session_data_send_action(struct ac_session_data_t* sessiondata, long action, long param, void* data, long length) {
struct capwap_list_item* item;
struct ac_session_action* actionsession;
struct capwap_list_item* search;
ASSERT(sessiondata != NULL);
ASSERT(length >= 0);
/* */
item = capwap_itemlist_create(sizeof(struct ac_session_action) + length);
actionsession = (struct ac_session_action*)item->item;
actionsession->action = action;
actionsession->param = param;
actionsession->length = length;
if (length > 0) {
ASSERT(data != NULL);
memcpy(actionsession->data, data, length);
}
/* Validate session data before use */
capwap_rwlock_rdlock(&g_ac.sessionslock);
search = g_ac.sessionsdata->first;
while (search != NULL) {
struct ac_session_data_t* sessiondata = (struct ac_session_data_t*)search->item;
if (sessiondata == (struct ac_session_data_t*)search->item) {
/* Append to actions list */
capwap_lock_enter(&sessiondata->sessionlock);
capwap_itemlist_insert_after(sessiondata->action, NULL, item);
capwap_event_signal(&sessiondata->waitpacket);
capwap_lock_exit(&sessiondata->sessionlock);
break;
}
/* */
search = search->next;
}
capwap_rwlock_exit(&g_ac.sessionslock);
}
/* Find AC sessions */
static struct ac_session_t* ac_search_session_from_wtpaddress(struct sockaddr_storage* address) {
static struct ac_session_t* ac_search_session_from_wtpaddress(union sockaddr_capwap* address) {
struct ac_session_t* result = NULL;
struct capwap_list_item* search;
@ -297,7 +230,7 @@ static struct ac_session_t* ac_search_session_from_wtpaddress(struct sockaddr_st
struct ac_session_t* session = (struct ac_session_t*)search->item;
ASSERT(session != NULL);
if (!capwap_compare_ip(address, &session->connection.remoteaddr)) {
if (!capwap_compare_ip(address, &session->dtls.peeraddr)) {
/* Increment session count */
capwap_lock_enter(&session->sessionlock);
session->count++;
@ -317,40 +250,6 @@ static struct ac_session_t* ac_search_session_from_wtpaddress(struct sockaddr_st
return result;
}
/* Find AC sessions data */
static struct ac_session_data_t* ac_search_session_data_from_wtpaddress(struct sockaddr_storage* address) {
struct ac_session_data_t* result = NULL;
struct capwap_list_item* search;
ASSERT(address != NULL);
capwap_rwlock_rdlock(&g_ac.sessionslock);
search = g_ac.sessionsdata->first;
while (search != NULL) {
struct ac_session_data_t* sessiondata = (struct ac_session_data_t*)search->item;
ASSERT(sessiondata != NULL);
if (!capwap_compare_ip(address, &sessiondata->connection.remoteaddr)) {
/* Increment session data count */
capwap_lock_enter(&sessiondata->sessionlock);
sessiondata->count++;
capwap_event_signal(&sessiondata->changereference);
capwap_lock_exit(&sessiondata->sessionlock);
/* */
result = sessiondata;
break;
}
search = search->next;
}
capwap_rwlock_exit(&g_ac.sessionslock);
return result;
}
/* Find session from wtp id */
struct ac_session_t* ac_search_session_from_wtpid(const char* wtpid) {
struct ac_session_t* result = NULL;
@ -365,7 +264,41 @@ struct ac_session_t* ac_search_session_from_wtpid(const char* wtpid) {
struct ac_session_t* session = (struct ac_session_t*)search->item;
ASSERT(session != NULL);
if (!strcmp(session->wtpid, wtpid)) {
if (session->wtpid && !strcmp(session->wtpid, wtpid)) {
/* Increment session count */
capwap_lock_enter(&session->sessionlock);
session->count++;
capwap_event_signal(&session->changereference);
capwap_lock_exit(&session->sessionlock);
/* */
result = session;
break;
}
search = search->next;
}
capwap_rwlock_exit(&g_ac.sessionslock);
return result;
}
/* Find session from wtp id */
struct ac_session_t* ac_search_session_from_sessionid(struct capwap_sessionid_element* sessionid) {
struct ac_session_t* result = NULL;
struct capwap_list_item* search;
ASSERT(sessionid != NULL);
capwap_rwlock_rdlock(&g_ac.sessionslock);
search = g_ac.sessions->first;
while (search != NULL) {
struct ac_session_t* session = (struct ac_session_t*)search->item;
ASSERT(session != NULL);
if (!memcmp(sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) {
/* Increment session count */
capwap_lock_enter(&session->sessionlock);
session->count++;
@ -468,14 +401,6 @@ void ac_session_close(struct ac_session_t* session) {
capwap_lock_exit(&session->sessionlock);
}
/* */
void ac_session_data_close(struct ac_session_data_t* sessiondata) {
capwap_lock_enter(&sessiondata->sessionlock);
sessiondata->running = 0;
capwap_event_signal(&sessiondata->waitpacket);
capwap_lock_exit(&sessiondata->sessionlock);
}
/* Close sessions */
static void ac_close_sessions() {
struct capwap_list_item* search;
@ -493,45 +418,18 @@ static void ac_close_sessions() {
search = search->next;
}
/* Session data */
search = g_ac.sessionsdata->first;
while (search != NULL) {
struct ac_session_data_t* sessiondata = (struct ac_session_data_t*)search->item;
ASSERT(sessiondata != NULL);
ac_session_data_close(sessiondata);
search = search->next;
}
capwap_rwlock_exit(&g_ac.sessionslock);
}
/* Detect data channel */
static int ac_is_plain_datachannel(void* buffer, int buffersize) {
struct capwap_preamble* preamble = (struct capwap_preamble*)buffer;
ASSERT(buffer != NULL);
ASSERT(buffersize > sizeof(struct capwap_preamble));
if ((preamble->type == CAPWAP_PREAMBLE_HEADER) && ((g_ac.descriptor.dtlspolicy & CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED) != 0)) {
return 1;
} else if ((preamble->type == CAPWAP_PREAMBLE_DTLS_HEADER) && ((g_ac.descriptor.dtlspolicy & CAPWAP_ACDESC_DTLS_DATA_CHANNEL_ENABLED) != 0)) {
return 0;
}
return -1;
}
/* Create new session */
static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddress, struct sockaddr_storage* acaddress, struct capwap_socket* sock) {
static struct ac_session_t* ac_create_session(int sock, union sockaddr_capwap* fromaddr, union sockaddr_capwap* toaddr) {
int result;
struct capwap_list_item* itemlist;
struct ac_session_t* session;
ASSERT(acaddress != NULL);
ASSERT(wtpaddress != NULL);
ASSERT(sock != NULL);
ASSERT(sock >= 0);
ASSERT(fromaddr != NULL);
ASSERT(toaddr != NULL);
/* Create new session */
itemlist = capwap_itemlist_create(sizeof(struct ac_session_t));
@ -541,9 +439,8 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres
session->itemlist = itemlist;
session->running = 1;
memcpy(&session->connection.socket, sock, sizeof(struct capwap_socket));
memcpy(&session->connection.localaddr, acaddress, sizeof(struct sockaddr_storage));
memcpy(&session->connection.remoteaddr, wtpaddress, sizeof(struct sockaddr_storage));
/* */
capwap_crypt_setconnection(&session->dtls, sock, toaddr, fromaddr);
/* */
ac_wlans_init(session);
@ -555,21 +452,19 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres
/* */
session->timeout = capwap_timeout_init();
session->idtimercontrol = capwap_timeout_createtimer(session->timeout);
session->idtimerkeepalivedead = capwap_timeout_createtimer(session->timeout);
/* Duplicate state for DFA */
memcpy(&session->dfa, &g_ac.dfa, sizeof(struct ac_state));
session->dfa.acipv4list.addresses = capwap_array_clone(g_ac.dfa.acipv4list.addresses);
session->dfa.acipv6list.addresses = capwap_array_clone(g_ac.dfa.acipv6list.addresses);
/* Add default AC list if empty*/
if ((session->dfa.acipv4list.addresses->count == 0) && (session->dfa.acipv6list.addresses->count == 0)) {
if (acaddress->ss_family == AF_INET) {
struct in_addr* acip = (struct in_addr*)capwap_array_get_item_pointer(session->dfa.acipv4list.addresses, 0);
memcpy(acip, &((struct sockaddr_in*)acaddress)->sin_addr, sizeof(struct in_addr));
} else if (acaddress->ss_family == AF_INET6) {
struct in6_addr* acip = (struct in6_addr*)capwap_array_get_item_pointer(session->dfa.acipv6list.addresses, 0);
memcpy(acip, &((struct sockaddr_in6*)acaddress)->sin6_addr, sizeof(struct in6_addr));
}
session->dfa.acipv4list.addresses = capwap_array_clone(g_ac.dfa.acipv4list.addresses);
if (!session->dfa.acipv4list.addresses->count && (session->dtls.localaddr.ss.ss_family == AF_INET)) {
memcpy(capwap_array_get_item_pointer(session->dfa.acipv4list.addresses, 0), &session->dtls.localaddr.sin.sin_addr, sizeof(struct in_addr));
}
session->dfa.acipv6list.addresses = capwap_array_clone(g_ac.dfa.acipv6list.addresses);
if (!session->dfa.acipv6list.addresses->count && (session->dtls.localaddr.ss.ss_family == AF_INET6)) {
memcpy(capwap_array_get_item_pointer(session->dfa.acipv6list.addresses, 0), &session->dtls.localaddr.sin6.sin6_addr, sizeof(struct in6_addr));
}
/* Init */
@ -610,73 +505,6 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres
return session;
}
/* Create new session data */
static struct ac_session_data_t* ac_create_session_data(struct sockaddr_storage* wtpaddress, struct sockaddr_storage* acaddress, struct capwap_socket* sock, int plain) {
int result;
struct capwap_list_item* itemlist;
struct ac_session_data_t* sessiondata;
ASSERT(acaddress != NULL);
ASSERT(wtpaddress != NULL);
ASSERT(sock != NULL);
/* Create new session data */
itemlist = capwap_itemlist_create(sizeof(struct ac_session_data_t));
sessiondata = (struct ac_session_data_t*)itemlist->item;
memset(sessiondata, 0, sizeof(struct ac_session_data_t));
/* */
sessiondata->itemlist = itemlist;
sessiondata->running = 1;
sessiondata->enabledtls = (plain ? 0 : 1);
/* */
sessiondata->count = 2;
capwap_event_init(&sessiondata->changereference);
/* */
sessiondata->timeout = capwap_timeout_init();
sessiondata->idtimercontrol = capwap_timeout_createtimer(sessiondata->timeout);
sessiondata->idtimerkeepalivedead = capwap_timeout_createtimer(sessiondata->timeout);
/* Connection info */
memcpy(&sessiondata->connection.socket, sock, sizeof(struct capwap_socket));
memcpy(&sessiondata->connection.localaddr, acaddress, sizeof(struct sockaddr_storage));
memcpy(&sessiondata->connection.remoteaddr, wtpaddress, sizeof(struct sockaddr_storage));
sessiondata->mtu = g_ac.mtu;
/* Init */
capwap_event_init(&sessiondata->waitpacket);
capwap_lock_init(&sessiondata->sessionlock);
sessiondata->action = capwap_list_create();
sessiondata->packets = capwap_list_create();
/* Update session data list */
capwap_rwlock_wrlock(&g_ac.sessionslock);
capwap_itemlist_insert_after(g_ac.sessionsdata, NULL, itemlist);
capwap_rwlock_exit(&g_ac.sessionslock);
/* Create thread */
result = pthread_create(&sessiondata->threadid, NULL, ac_session_data_thread, (void*)sessiondata);
if (!result) {
struct ac_session_thread_t* sessionthread;
/* Keeps trace of active threads */
itemlist = capwap_itemlist_create(sizeof(struct ac_session_thread_t));
sessionthread = (struct ac_session_thread_t*)itemlist->item;
sessionthread->threadid = sessiondata->threadid;
/* */
capwap_itemlist_insert_after(g_ac.sessionsthread, NULL, itemlist);
} else {
capwap_logging_fatal("Unable create session data thread, error code %d", result);
capwap_exit(CAPWAP_OUT_OF_MEMORY);
}
return sessiondata;
}
/* Release reference of session */
void ac_session_release_reference(struct ac_session_t* session) {
ASSERT(session != NULL);
@ -688,17 +516,6 @@ void ac_session_release_reference(struct ac_session_t* session) {
capwap_lock_exit(&session->sessionlock);
}
/* Release reference of session data */
void ac_session_data_release_reference(struct ac_session_data_t* sessiondata) {
ASSERT(sessiondata != NULL);
capwap_lock_enter(&sessiondata->sessionlock);
ASSERT(sessiondata->count > 0);
sessiondata->count--;
capwap_event_signal(&sessiondata->changereference);
capwap_lock_exit(&sessiondata->sessionlock);
}
/* Update statistics */
void ac_update_statistics(void) {
@ -816,15 +633,17 @@ int ac_execute(void) {
int index;
int check;
struct capwap_socket socket;
struct sockaddr_storage recvfromaddr;
struct sockaddr_storage recvtoaddr;
union sockaddr_capwap fromaddr;
union sockaddr_capwap toaddr;
struct ac_session_t* session;
char buffer[CAPWAP_MAX_PACKET_SIZE];
int buffersize;
struct ac_fds fds;
/* Set file descriptor pool */
if (ac_execute_init_fdspool(&g_ac.fds, &g_ac.net, g_ac.fdmsgsessions[1]) <= 0) {
if (ac_execute_init_fdspool(&fds, &g_ac.net, g_ac.fdmsgsessions[1]) <= 0) {
capwap_logging_debug("Unable to initialize file descriptor pool");
return AC_ERROR_SYSTEM_FAILER;
}
@ -837,14 +656,14 @@ int ac_execute(void) {
/* Start discovery thread */
if (!ac_discovery_start()) {
ac_execute_free_fdspool(&g_ac.fds);
ac_execute_free_fdspool(&fds);
capwap_logging_debug("Unable to start discovery thread");
return AC_ERROR_SYSTEM_FAILER;
}
/* Enable Backend Management */
if (!ac_backend_start()) {
ac_execute_free_fdspool(&g_ac.fds);
ac_execute_free_fdspool(&fds);
ac_discovery_stop();
capwap_logging_error("Unable start backend management");
return AC_ERROR_SYSTEM_FAILER;
@ -854,7 +673,7 @@ int ac_execute(void) {
while (g_ac.running) {
/* Receive packet */
buffersize = sizeof(buffer);
index = ac_recvfrom(&g_ac.fds, buffer, &buffersize, &recvfromaddr, &recvtoaddr);
index = ac_recvfrom(&fds, buffer, &buffersize, &fromaddr, &toaddr);
if (!g_ac.running) {
capwap_logging_debug("Closing AC");
break;
@ -862,119 +681,62 @@ int ac_execute(void) {
/* */
if (index >= 0) {
/* Detect local address */
if (recvtoaddr.ss_family == AF_UNSPEC) {
if (capwap_get_localaddress_by_remoteaddress(&recvtoaddr, &recvfromaddr, g_ac.net.bind_interface, (!(g_ac.net.bind_ctrl_flags & CAPWAP_IPV6ONLY_FLAG) ? 1 : 0))) {
struct sockaddr_storage sockinfo;
socklen_t sockinfolen = sizeof(struct sockaddr_storage);
/* Search the AC session */
session = ac_search_session_from_wtpaddress(&fromaddr);
if (session) {
/* Add packet*/
ac_session_add_packet(session, buffer, buffersize, 0);
memset(&sockinfo, 0, sizeof(struct sockaddr_storage));
if (getsockname(g_ac.fds.fdspoll[index].fd, (struct sockaddr*)&sockinfo, &sockinfolen) < 0) {
break;
}
/* Release reference */
ac_session_release_reference(session);
} else {
unsigned short sessioncount;
CAPWAP_SET_NETWORK_PORT(&recvtoaddr, CAPWAP_GET_NETWORK_PORT(&sockinfo));
}
}
/* TODO prevent dos attack add filtering ip for multiple error */
/* Retrieve network information */
capwap_get_network_socket(&g_ac.net, &socket, g_ac.fds.fdspoll[index].fd);
/* Get current session number */
capwap_rwlock_rdlock(&g_ac.sessionslock);
sessioncount = g_ac.sessions->count;
capwap_rwlock_exit(&g_ac.sessionslock);
/* Search the AC session / session data */
if (socket.isctrlsocket) {
struct ac_session_t* session = ac_search_session_from_wtpaddress(&recvfromaddr);
/* */
if (ac_backend_isconnect() && (sessioncount < g_ac.descriptor.maxwtp)) {
check = capwap_sanity_check(CAPWAP_UNDEF_STATE, buffer, buffersize, g_ac.enabledtls);
if (check == CAPWAP_PLAIN_PACKET) {
struct capwap_header* header = (struct capwap_header*)buffer;
if (session) {
/* Add packet*/
ac_session_add_packet(session, buffer, buffersize, 0);
/* Accepted only packet without fragmentation */
if (!IS_FLAG_F_HEADER(header)) {
int headersize = GET_HLEN_HEADER(header) * 4;
if (buffersize >= (headersize + sizeof(struct capwap_control_message))) {
struct capwap_control_message* control = (struct capwap_control_message*)((char*)buffer + headersize);
unsigned long type = ntohl(control->type);
/* Release reference */
ac_session_release_reference(session);
} else {
unsigned short sessioncount;
if (type == CAPWAP_DISCOVERY_REQUEST) {
ac_discovery_add_packet(buffer, buffersize, fds.fdspoll[index].fd, &fromaddr);
} else if (!g_ac.enabledtls && (type == CAPWAP_JOIN_REQUEST)) {
/* Create a new session */
session = ac_create_session(fds.fdspoll[index].fd, &fromaddr, &toaddr);
ac_session_add_packet(session, buffer, buffersize, 1);
/* TODO prevent dos attack add filtering ip for multiple error */
/* Get current session number */
capwap_rwlock_rdlock(&g_ac.sessionslock);
sessioncount = g_ac.sessions->count;
capwap_rwlock_exit(&g_ac.sessionslock);
/* */
if (ac_backend_isconnect() && (sessioncount < g_ac.descriptor.maxwtp)) {
check = capwap_sanity_check(1, CAPWAP_UNDEF_STATE, buffer, buffersize, g_ac.enabledtls, 0);
if (check == CAPWAP_PLAIN_PACKET) {
struct capwap_header* header = (struct capwap_header*)buffer;
/* Accepted only packet without fragmentation */
if (!IS_FLAG_F_HEADER(header)) {
int headersize = GET_HLEN_HEADER(header) * 4;
if (buffersize >= (headersize + sizeof(struct capwap_control_message))) {
struct capwap_control_message* control = (struct capwap_control_message*)((char*)buffer + headersize);
unsigned long type = ntohl(control->type);
if (type == CAPWAP_DISCOVERY_REQUEST) {
ac_discovery_add_packet(buffer, buffersize, g_ac.fds.fdspoll[index].fd, &recvfromaddr);
} else if (!g_ac.enabledtls && (type == CAPWAP_JOIN_REQUEST)) {
/* Create a new session */
session = ac_create_session(&recvfromaddr, &recvtoaddr, &socket);
ac_session_add_packet(session, buffer, buffersize, 1);
/* Release reference */
ac_session_release_reference(session);
}
/* Release reference */
ac_session_release_reference(session);
}
}
} else if (check == CAPWAP_DTLS_PACKET) {
/* Before create new session check if receive DTLS Client Hello */
if (capwap_crypt_has_dtls_clienthello(&((char*)buffer)[sizeof(struct capwap_dtls_header)], buffersize - sizeof(struct capwap_dtls_header))) {
/* Create a new session */
session = ac_create_session(&recvfromaddr, &recvtoaddr, &socket);
ac_session_add_packet(session, buffer, buffersize, 0);
/* Release reference */
ac_session_release_reference(session);
}
}
}
}
} else {
struct ac_session_data_t* sessiondata = ac_search_session_data_from_wtpaddress(&recvfromaddr);
} else if (check == CAPWAP_DTLS_PACKET) {
/* Before create new session check if receive DTLS Client Hello */
if (capwap_crypt_has_dtls_clienthello(&((char*)buffer)[sizeof(struct capwap_dtls_header)], buffersize - sizeof(struct capwap_dtls_header))) {
/* Create a new session */
session = ac_create_session(fds.fdspoll[index].fd, &fromaddr, &toaddr);
ac_session_add_packet(session, buffer, buffersize, 0);
if (sessiondata) {
/* Add packet*/
ac_session_data_add_packet(sessiondata, buffer, buffersize, 0);
/* Release reference */
ac_session_data_release_reference(sessiondata);
} else {
int plain;
/* TODO prevent dos attack add filtering ip for multiple error */
/* Detect type data channel */
plain = ac_is_plain_datachannel(buffer, buffersize);
/* Before create new session check if receive DTLS Client Hello */
if (!plain) {
if (buffersize <= sizeof(struct capwap_dtls_header)) {
plain = -1;
} else if (!capwap_crypt_has_dtls_clienthello(&((char*)buffer)[sizeof(struct capwap_dtls_header)], buffersize - sizeof(struct capwap_dtls_header))) {
plain = -1;
/* Release reference */
ac_session_release_reference(session);
}
}
/* */
if (plain >= 0) {
/* Create a new session */
sessiondata = ac_create_session_data(&recvfromaddr, &recvtoaddr, &socket, plain);
ac_session_data_add_packet(sessiondata, buffer, buffersize, 0);
/* Release reference */
ac_session_data_release_reference(sessiondata);
}
}
}
}
} else if ((index == CAPWAP_RECV_ERROR_INTR) || (index == AC_RECV_NOERROR_MSGQUEUE) || (index == AC_RECV_NOERROR_KMODEVENT)) {
/* Ignore recv */
continue;
@ -1000,6 +762,6 @@ int ac_execute(void) {
ac_backend_free();
/* Free file description pool */
ac_execute_free_fdspool(&g_ac.fds);
ac_execute_free_fdspool(&fds);
return result;
}