Exemplo n.º 1
0
/* Teardown connection */
void ac_session_teardown(struct ac_session_t* session) {
	ASSERT(session != NULL);

	/* Remove session from list */
	capwap_rwlock_wrlock(&g_ac.sessionslock);
	capwap_itemlist_remove(g_ac.sessions, session->itemlist);
	capwap_rwlock_unlock(&g_ac.sessionslock);

	/* Remove all pending packets */
	while (session->packets->count > 0) {
		capwap_itemlist_free(capwap_itemlist_remove_head(session->packets));
	}

	/* Close DTSL Control */
	if (session->dtls.enable) {
		capwap_crypt_close(&session->dtls);
	}

	/* Cancel all notify event */
	if (session->notifyevent->first) {
		char buffer[5];
		struct ac_soap_response* response;

		capwap_itoa(SOAP_EVENT_STATUS_CANCEL, buffer);
		while (session->notifyevent->first != NULL) {
			struct ac_session_notify_event_t* notify = (struct ac_session_notify_event_t*)session->notifyevent->first->item;

			/* Cancel event */
			response = ac_soap_updatebackendevent(session, notify->idevent, buffer);
			if (response) {
				ac_soapclient_free_response(response);
			}

			/* Remove notify event */
			capwap_itemlist_free(capwap_itemlist_remove(session->notifyevent, session->notifyevent->first));
		}
	}

	/* Remove timer */
	if (session->idtimercontrol != CAPWAP_TIMEOUT_INDEX_NO_SET) {
		capwap_timeout_unset(session->timeout, session->idtimercontrol);
		session->idtimercontrol = CAPWAP_TIMEOUT_INDEX_NO_SET;
	}

	if (session->idtimerkeepalivedead != CAPWAP_TIMEOUT_INDEX_NO_SET) {
		capwap_timeout_unset(session->timeout, session->idtimerkeepalivedead);
		session->idtimerkeepalivedead = CAPWAP_TIMEOUT_INDEX_NO_SET;
	}

	/* */
	ac_dfa_change_state(session, CAPWAP_DTLS_TEARDOWN_STATE);
}
Exemplo n.º 2
0
void capwap_list_flush(struct capwap_list* list) {
	struct capwap_list_item* item;
	struct capwap_list_item* next;

	ASSERT(list != NULL);

	item = list->first;
	while (item) {
		next = item->next;
		capwap_itemlist_free(item);
		item = next;
	}

	list->first = NULL;
	list->last = NULL;
	list->count = 0;
}
Exemplo n.º 3
0
void capwap_timeout_unset(struct capwap_timeout* timeout, unsigned long index) {
	struct capwap_list_item* itemlist;

	ASSERT(timeout != NULL);

	if (index != CAPWAP_TIMEOUT_INDEX_NO_SET) {
		itemlist = (struct capwap_list_item*)capwap_hash_search(timeout->itemsreference, &index);
		if (itemlist) {
#ifdef CAPWAP_TIMEOUT_LOGGING_DEBUG
			log_printf(LOG_DEBUG, "Unset timeout: %lu", index);
#endif

			/* */
			capwap_hash_delete(timeout->itemsreference, &index);
			capwap_itemlist_free(capwap_itemlist_remove(timeout->itemstimeout, itemlist));
		}
	}
}
Exemplo n.º 4
0
static void ac_session_msgqueue_parsing_item(struct ac_session_msgqueue_item_t* item) {
	switch (item->message) {
		case AC_MESSAGE_QUEUE_CLOSE_THREAD: {
			struct capwap_list_item* search = g_ac.sessionsthread->first;
			while (search != NULL) {
				struct ac_session_thread_t* sessionthread = (struct ac_session_thread_t*)search->item;
				ASSERT(sessionthread != NULL);

				if (sessionthread->threadid == item->message_close_thread.threadid) {
					void* dummy;

					/* Clean thread resource */
					pthread_join(sessionthread->threadid, &dummy);
					capwap_itemlist_free(capwap_itemlist_remove(g_ac.sessionsthread, search));
					break;
				}

				/* */
				search = search->next;
			}

			break;
		}

		case AC_MESSAGE_QUEUE_UPDATE_CONFIGURATION: {
			ac_update_configuration(item->message_configuration.jsonroot);

			/* Free JSON */
			json_object_put(item->message_configuration.jsonroot);
			break;
		}

		case AC_MESSAGE_QUEUE_CLOSE_ALLSESSIONS: {
			ac_close_sessions();		/* Close all sessions */
			break;
		}

		default: {
			capwap_logging_debug("Unknown message queue item: %lu", item->message);
			break;
		}
	}
}
Exemplo n.º 5
0
unsigned long capwap_timeout_hasexpired(struct capwap_timeout* timeout) {
	long delta;
	struct capwap_timeout_item* item;
	struct capwap_list_item* itemlist;
	unsigned long index;
	capwap_timeout_expire callback;
	void* context;
	void* param;

	ASSERT(timeout != NULL);

	/* */
	delta = capwap_timeout_getcoming(timeout);
	if ((delta > 0) || (delta == CAPWAP_TIMEOUT_INFINITE))  {
		return 0;
	}

	/* */
	itemlist = capwap_itemlist_remove_head(timeout->itemstimeout);
	item = (struct capwap_timeout_item*)itemlist->item;

#ifdef CAPWAP_TIMEOUT_LOGGING_DEBUG
	log_printf(LOG_DEBUG, "Expired timeout: %lu", item->index);
#endif

	/* Cache callback before release timeout timer */
	index = item->index;
	callback = item->callback;
	context = item->context;
	param = item->param;

	/* Free memory */
	capwap_hash_delete(timeout->itemsreference, &index);
	capwap_itemlist_free(itemlist);

	/* */
	if (callback) {
		callback(timeout, index, context, param);
	}

	return index;
}
Exemplo n.º 6
0
/* Change WTP state machine */
void ac_dfa_change_state(struct ac_session_t* session, int state) {
	struct capwap_list_item* search;

	ASSERT(session != NULL);

	if (state != session->state) {
#ifdef DEBUG
		char sessionname[33];
		capwap_sessionid_printf(&session->sessionid, sessionname);
		capwap_logging_debug("Session AC %s change state from %s to %s", sessionname, capwap_dfa_getname(session->state), capwap_dfa_getname(state));
#endif

		session->state = state;

		/* Search into notify event */
		search = session->notifyevent->first;
		while (search != NULL) {
			struct ac_session_notify_event_t* notify = (struct ac_session_notify_event_t*)search->item;

			if ((notify->action == NOTIFY_ACTION_CHANGE_STATE) && (notify->session_state == state)) {
				char buffer[4];
				struct ac_soap_response* response;

				/* */
				response = ac_soap_updatebackendevent(session, notify->idevent, capwap_itoa(SOAP_EVENT_STATUS_COMPLETE, buffer));
				if (response) {
					ac_soapclient_free_response(response);
				}

				/* Remove notify event */
				capwap_itemlist_free(capwap_itemlist_remove(session->notifyevent, search));
				break;
			}

			search = search->next;
		}
	}
}
Exemplo n.º 7
0
static void ac_session_run(struct ac_session_t* session) {
	int res;
	int check;
	int length;
	struct capwap_list_item* search;
	char buffer[CAPWAP_MAX_PACKET_SIZE];

	ASSERT(session != NULL);

	/* Configure DFA */
	if (g_ac.enabledtls) {
		if (!ac_dtls_setup(session)) {
			ac_session_teardown(session);			/* Teardown connection */
		}
	} else {
		/* Wait Join request */
		ac_dfa_change_state(session, CAPWAP_JOIN_STATE);
		capwap_timeout_set(session->timeout, session->idtimercontrol, AC_JOIN_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
	}

	while (session->state != CAPWAP_DTLS_TEARDOWN_STATE) {
		/* Get packet */
		length = ac_network_read(session, buffer, sizeof(buffer));
		if (length < 0) {
			if ((length == CAPWAP_ERROR_SHUTDOWN) || (length == CAPWAP_ERROR_CLOSE)) {
				ac_session_teardown(session);
			}
		} else if (length > 0) {
			/* Check generic capwap packet */
			check = capwap_sanity_check(CAPWAP_UNDEF_STATE, buffer, length, 0);
			if (check == CAPWAP_PLAIN_PACKET) {
				struct capwap_parsed_packet packet;

				/* Defragment management */
				if (!session->rxmngpacket) {
					session->rxmngpacket = capwap_packet_rxmng_create_message();
				}

				/* If request, defragmentation packet */
				check = capwap_packet_rxmng_add_recv_packet(session->rxmngpacket, buffer, length);
				if (check == CAPWAP_RECEIVE_COMPLETE_PACKET) {
					/* Receive all fragment */
					if (capwap_is_request_type(session->rxmngpacket->ctrlmsg.type) && (session->remotetype == session->rxmngpacket->ctrlmsg.type) && (session->remoteseqnumber == session->rxmngpacket->ctrlmsg.seq)) {
						/* Retransmit response */
						if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->responsefragmentpacket)) {
							capwap_logging_error("Error to resend response packet");
						} else {
							capwap_logging_debug("Retrasmitted control packet");
						}
					} else {
						/* Check message type */
						res = capwap_check_message_type(session->rxmngpacket);
						if (res == VALID_MESSAGE_TYPE) {
							res = capwap_parsing_packet(session->rxmngpacket, &packet);
							if (res == PARSING_COMPLETE) {
								int hasrequest = capwap_is_request_type(session->rxmngpacket->ctrlmsg.type);

								/* Validate packet */
								if (!capwap_validate_parsed_packet(&packet, NULL)) {
									/* Search into notify event */
									search = session->notifyevent->first;
									while (search != NULL) {
										struct ac_session_notify_event_t* notify = (struct ac_session_notify_event_t*)search->item;

										if (hasrequest && (notify->action == NOTIFY_ACTION_RECEIVE_REQUEST_CONTROLMESSAGE)) {
											char buffer[4];
											struct ac_soap_response* response;

											/* */
											response = ac_soap_updatebackendevent(session, notify->idevent, capwap_itoa(SOAP_EVENT_STATUS_COMPLETE, buffer));
											if (response) {
												ac_soapclient_free_response(response);
											}

											/* Remove notify event */
											capwap_itemlist_free(capwap_itemlist_remove(session->notifyevent, search));
											break;
										} else if (!hasrequest && (notify->action == NOTIFY_ACTION_RECEIVE_RESPONSE_CONTROLMESSAGE)) {
											char buffer[4];
											struct ac_soap_response* response;
											struct capwap_resultcode_element* resultcode;

											/* Check the success of the Request */
											resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(&packet, CAPWAP_ELEMENT_RESULTCODE);
											response = ac_soap_updatebackendevent(session, notify->idevent, capwap_itoa(((!resultcode || CAPWAP_RESULTCODE_OK(resultcode->code)) ? SOAP_EVENT_STATUS_COMPLETE : SOAP_EVENT_STATUS_GENERIC_ERROR), buffer));
											if (response) {
												ac_soapclient_free_response(response);
											}

											/* Remove notify event */
											capwap_itemlist_free(capwap_itemlist_remove(session->notifyevent, search));
											break;
										}

										search = search->next;
									}

									/* */
									ac_dfa_execute(session, &packet);
								} else {
									capwap_logging_debug("Failed validation parsed control packet");
									if (capwap_is_request_type(session->rxmngpacket->ctrlmsg.type)) {
										capwap_logging_warning("Missing Mandatory Message Element, send Response Packet with error");
										ac_send_invalid_request(session, CAPWAP_RESULTCODE_FAILURE_MISSING_MANDATORY_MSG_ELEMENT);
									}
								}
							} else {
								capwap_logging_debug("Failed parsing packet");
								if ((res == UNRECOGNIZED_MESSAGE_ELEMENT) && capwap_is_request_type(session->rxmngpacket->ctrlmsg.type)) {
									capwap_logging_warning("Unrecognized Message Element, send Response Packet with error");
									ac_send_invalid_request(session, CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT);
									/* TODO: add the unrecognized message element */
								}
							}
						} else {
							capwap_logging_debug("Invalid message type");
							if (res == INVALID_REQUEST_MESSAGE_TYPE) {
								capwap_logging_warning("Unexpected Unrecognized Request, send Response Packet with error");
								ac_send_invalid_request(session, CAPWAP_RESULTCODE_MSG_UNEXPECTED_UNRECOGNIZED_REQUEST);
							}
						}
					}

					/* Free memory */
					capwap_free_parsed_packet(&packet);
					if (session->rxmngpacket) {
						capwap_packet_rxmng_free(session->rxmngpacket);
						session->rxmngpacket = NULL;
					}
				} else if (check != CAPWAP_REQUEST_MORE_FRAGMENT) {
					/* Discard fragments */
					if (session->rxmngpacket) {
						capwap_packet_rxmng_free(session->rxmngpacket);
						session->rxmngpacket = NULL;
					}
				}
			}
		}
	}

	/* Wait teardown timeout before kill session */
	capwap_timeout_wait(AC_DTLS_SESSION_DELETE_INTERVAL);
	ac_dfa_state_teardown(session);

	/* Release reference session */
	ac_session_destroy(session);
}
Exemplo n.º 8
0
/* Release reference of session */
static void ac_session_destroy(struct ac_session_t* session) {
#ifdef DEBUG
	char sessionname[33];
#endif

	ASSERT(session != NULL);

#ifdef DEBUG
	capwap_sessionid_printf(&session->sessionid, sessionname);
	capwap_logging_debug("Release Session AC %s", sessionname);
#endif

	/* Release last reference */
	capwap_lock_enter(&session->sessionlock);
	session->count--;

	/* Terminate SOAP request pending */
	if (session->soaprequest) {
		ac_soapclient_shutdown_request(session->soaprequest);
	}

	/* Check if all reference is release */
	while (session->count > 0) {
#ifdef DEBUG
		capwap_logging_debug("Wait for release Session AC %s (count=%d)", sessionname, session->count);
#endif
		/* */
		capwap_event_reset(&session->changereference);
		capwap_lock_exit(&session->sessionlock);

		/* Wait */
		capwap_event_wait(&session->changereference);

		capwap_lock_enter(&session->sessionlock);
	}

	capwap_lock_exit(&session->sessionlock);

	/* Close data channel */
	ac_kmod_delete_datasession(&session->sessionid);

	/* Free DTSL Control */
	capwap_crypt_freesession(&session->dtls);

	/* Free resource */
	while (session->packets->count > 0) {
		capwap_itemlist_free(capwap_itemlist_remove_head(session->packets));
	}

	/* Free WLANS */
	ac_wlans_destroy(session);

	/* */
	capwap_event_destroy(&session->changereference);
	capwap_event_destroy(&session->waitpacket);
	capwap_lock_destroy(&session->sessionlock);
	capwap_list_free(session->action);
	capwap_list_free(session->packets);

	/* Free fragments packet */
	if (session->rxmngpacket) {
		capwap_packet_rxmng_free(session->rxmngpacket);
	}

	capwap_list_free(session->requestfragmentpacket);
	capwap_list_free(session->responsefragmentpacket);
	capwap_list_free(session->notifyevent);
	capwap_timeout_free(session->timeout);

	/* Free DFA resource */
	capwap_array_free(session->dfa.acipv4list.addresses);
	capwap_array_free(session->dfa.acipv6list.addresses);

	if (session->wtpid) {
		capwap_free(session->wtpid);
	}

	/* Free item */
	capwap_itemlist_free(session->itemlist);
}
Exemplo n.º 9
0
static int ac_network_read(struct ac_session_t* session, void* buffer, int length) {
	int result = 0;
	long waittimeout;
	
	ASSERT(session != NULL);
	ASSERT(buffer != NULL);
	ASSERT(length > 0);

	for (;;) {
		capwap_lock_enter(&session->sessionlock);

		if (!session->running) {
			capwap_lock_exit(&session->sessionlock);
			return CAPWAP_ERROR_CLOSE;
		} else if (!session->requestfragmentpacket->count && (session->action->count > 0)) {
			struct capwap_list_item* itemaction;

			itemaction = capwap_itemlist_remove_head(session->action);
			capwap_lock_exit(&session->sessionlock);

			/* */
			result = ac_session_action_execute(session, (struct ac_session_action*)itemaction->item);

			/* Free packet */
			capwap_itemlist_free(itemaction);
			return result;
		} else if (session->packets->count > 0) {
			struct capwap_list_item* itempacket;

			/* Get packet */
			itempacket = capwap_itemlist_remove_head(session->packets);
			capwap_lock_exit(&session->sessionlock);

			if (itempacket) {
				struct ac_packet* packet = (struct ac_packet*)itempacket->item;
				long packetlength = itempacket->itemsize - sizeof(struct ac_packet);
				
				if (!packet->plainbuffer && session->dtls.enable) {
					int oldaction = session->dtls.action;

					/* Decrypt packet */
					result = capwap_decrypt_packet(&session->dtls, packet->buffer, packetlength, buffer, length);
					if (result == CAPWAP_ERROR_AGAIN) {
						/* Check is handshake complete */
						if ((oldaction == CAPWAP_DTLS_ACTION_HANDSHAKE) && (session->dtls.action == CAPWAP_DTLS_ACTION_DATA)) {
							if (session->state == CAPWAP_DTLS_CONNECT_STATE) {
								ac_dfa_change_state(session, CAPWAP_JOIN_STATE);
								capwap_timeout_set(session->timeout, session->idtimercontrol, AC_JOIN_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
							}
						}
					}
				} else {
					if (packetlength <= length) {
						memcpy(buffer, packet->buffer, packetlength);
						result = packetlength;
					}
				}

				/* Free packet */
				capwap_itemlist_free(itempacket);
			}

			return result;
		}

		capwap_lock_exit(&session->sessionlock);

		/* Get timeout */
		waittimeout = capwap_timeout_getcoming(session->timeout);
		if (!waittimeout) {
			capwap_timeout_hasexpired(session->timeout);
			return AC_ERROR_TIMEOUT;
		}

		/* Wait packet */
		capwap_event_wait_timeout(&session->waitpacket, waittimeout);
	}

	return 0;
}
Exemplo n.º 10
0
static void ac_discovery_run(void) {
	int sizedata;
	struct capwap_list_item* itempacket;
	struct ac_discovery_packet* acpacket;
	struct capwap_parsed_packet packet;
	struct capwap_packet_rxmng* rxmngpacket;

	while (!g_ac_discovery.endthread) {
		/* Get packet */
		capwap_lock_enter(&g_ac_discovery.packetslock);

		itempacket = NULL; 
		if (g_ac_discovery.packets->count > 0) {
			itempacket = capwap_itemlist_remove_head(g_ac_discovery.packets);
		}

		capwap_lock_exit(&g_ac_discovery.packetslock);

		if (!itempacket) {
			/* Wait packet with timeout*/
			if (!capwap_event_wait_timeout(&g_ac_discovery.waitpacket, AC_DISCOVERY_CLEANUP_TIMEOUT)) {
				ac_discovery_cleanup();
			}
			
			continue;
		}

		/* */
		acpacket = (struct ac_discovery_packet*)itempacket->item;
		sizedata = itempacket->itemsize - sizeof(struct ac_discovery_packet);

		/* Accept only discovery request don't fragment */
		rxmngpacket = capwap_packet_rxmng_create_message();
		if (capwap_packet_rxmng_add_recv_packet(rxmngpacket, acpacket->data, sizedata) == CAPWAP_RECEIVE_COMPLETE_PACKET) {
			/* Validate message */
			if (capwap_check_message_type(rxmngpacket) == VALID_MESSAGE_TYPE) {
				/* Parsing packet */
				if (capwap_parsing_packet(rxmngpacket, &packet) == PARSING_COMPLETE) {
					/* Validate packet */
					if (!capwap_validate_parsed_packet(&packet, NULL)) {
						struct capwap_packet_txmng* txmngpacket;

						/* */
						capwap_logging_debug("Receive discovery request packet");

						/* Creare discovery response */
						txmngpacket = ac_create_discovery_response(&packet);
						if (txmngpacket) {
							struct capwap_list* responsefragmentpacket;

							/* Discovery response complete, get fragment packets */
							responsefragmentpacket = capwap_list_create();
							capwap_packet_txmng_get_fragment_packets(txmngpacket, responsefragmentpacket, g_ac_discovery.fragmentid);
							if (responsefragmentpacket->count > 1) {
								g_ac_discovery.fragmentid++;
							}

							/* Free packets manager */
							capwap_packet_txmng_free(txmngpacket);

							/* Send discovery response to WTP */
							if (!capwap_sendto_fragmentpacket(acpacket->sendsock, responsefragmentpacket, &acpacket->sender)) {
								capwap_logging_debug("Warning: error to send discovery response packet");
							}

							/* Don't buffering a packets sent */
							capwap_list_free(responsefragmentpacket);
						}
					}
				}

				/* Free resource */
				capwap_free_parsed_packet(&packet);
			}
		}

		/* Free resource */
		capwap_packet_rxmng_free(rxmngpacket);

		/* Free packet */
		capwap_itemlist_free(itempacket);
	}
}