Ejemplo n.º 1
0
static int ac_backend_soap_update_event(const char* idevent, int status) {
	int result = 0;
	char buffer[256];
	struct ac_soap_request* request = NULL;
	struct ac_http_soap_server* server;

	ASSERT(g_ac_backend.soaprequest == NULL);
	ASSERT(g_ac_backend.backendsessionid != NULL);

	/* Get HTTP Soap Server */
	server = ac_backend_get_server();

	/* Critical section */
	capwap_lock_enter(&g_ac_backend.lock);

	/* Build Soap Request */
	if (!g_ac_backend.endthread) {
		request = ac_soapclient_create_request("updateBackendEvent", SOAP_NAMESPACE_URI);
		if (request) {
			ac_soapclient_add_param(request, "xs:string", "idsession", g_ac_backend.backendsessionid);
			ac_soapclient_add_param(request, "xs:string", "idevent", idevent);
			ac_soapclient_add_param(request, "xs:int", "status", capwap_itoa(status, buffer));
			g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server);
		}
	}

	capwap_lock_exit(&g_ac_backend.lock);

	/* */
	if (!g_ac_backend.soaprequest) {
		if (request) {
			ac_soapclient_free_request(request);
		}

		return 0;
	}

	/* Send Request & Recv Response */
	if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) {
		struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest);
		if (response) {
			ac_soapclient_free_response(response);
		}
	}

	/* Critical section */
	capwap_lock_enter(&g_ac_backend.lock);

	/* Free resource */
	ac_soapclient_close_request(g_ac_backend.soaprequest, 1);
	g_ac_backend.soaprequest = NULL;

	capwap_lock_exit(&g_ac_backend.lock);

	return result;
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
0
static void ac_backend_soap_leave(void) {
	struct ac_soap_request* request;
	struct ac_http_soap_server* server;

	ASSERT(g_ac_backend.soaprequest == NULL);

	/* */
	if (!g_ac_backend.backendstatus || !g_ac_backend.backendsessionid) {
		return;
	}

	/* Get HTTP Soap Server */
	server = ac_backend_get_server();

	/* Critical section */
	capwap_lock_enter(&g_ac_backend.lock);

	/* Build Soap Request */
	request = ac_soapclient_create_request("leaveBackend", SOAP_NAMESPACE_URI);
	if (request) {
		ac_soapclient_add_param(request, "xs:string", "idsession", g_ac_backend.backendsessionid);
		g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server);
	}

	capwap_lock_exit(&g_ac_backend.lock);

	/* */
	if (!g_ac_backend.soaprequest) {
		if (request) {
			ac_soapclient_free_request(request);
		}

		return;
	}

	/* Send Request & Recv Response */
	if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) {
		struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest);
		if (response) {
			ac_soapclient_free_response(response);
		}
	}

	/* Critical section */
	capwap_lock_enter(&g_ac_backend.lock);

	/* Free resource */
	ac_soapclient_close_request(g_ac_backend.soaprequest, 1);
	g_ac_backend.soaprequest = NULL;

	capwap_lock_exit(&g_ac_backend.lock);
}
Ejemplo n.º 4
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;
		}
	}
}
Ejemplo n.º 5
0
static int ac_session_action_station_configuration_ieee8011_add_station(struct ac_session_t* session, struct ac_notify_station_configuration_ieee8011_add_station* notify) {
	struct ac_soap_response* response;

	ASSERT(session->requestfragmentpacket->count == 0);

	/* Check if RADIO id and WLAN id is valid */
	if (!IS_VALID_RADIOID(notify->radioid) || !IS_VALID_WLANID(notify->wlanid)) {
		return AC_NO_ERROR;
	}

	/* Need authorization of Director */
	response = ac_session_action_authorizestation_request(session, notify->radioid, notify->wlanid, notify->address);
	if (response) {
		if (ac_session_action_authorizestation_response(session, response, notify)) {
			capwap_logging_info("Station is not authorized");
			/* TODO kickoff station */
		}

		ac_soapclient_free_response(response);
	}

	return AC_NO_ERROR;
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
0
static int ac_session_action_execute(struct ac_session_t* session, struct ac_session_action* action) {
	int result = AC_NO_ERROR;

	switch (action->action) {
		case AC_SESSION_ACTION_CLOSE: {
			result = CAPWAP_ERROR_CLOSE;
			break;
		}

		case AC_SESSION_ACTION_RESET_WTP: {
			result = ac_session_action_resetwtp(session, (struct ac_notify_reset_t*)action->data);
			break;
		}

		case AC_SESSION_ACTION_ADDWLAN: {
			result = ac_session_action_addwlan(session, (struct ac_notify_addwlan_t*)action->data);
			break;
		}

		case AC_SESSION_ACTION_RECV_KEEPALIVE: {
#ifdef DEBUG
			{
				char sessionname[33];
				capwap_sessionid_printf(&session->sessionid, sessionname);
				capwap_logging_debug("Receive Keep-Alive from %s", sessionname);
			}
#endif
			/* Send keep-alive response */
			//ac_kmod_send_keepalive(&session->sessionid);
			capwap_timeout_set(session->timeout, session->idtimerkeepalivedead, AC_MAX_DATA_KEEPALIVE_INTERVAL, ac_dfa_teardown_timeout, session, NULL);

			/* */
			if (session->state == CAPWAP_DATA_CHECK_TO_RUN_STATE) {
				struct ac_soap_response* response;

				/* Capwap handshake complete, notify event to backend */
				response = ac_soap_runningwtpsession(session, session->wtpid);
				if (response) {
					if (response->responsecode == HTTP_RESULT_OK) {
						ac_dfa_change_state(session, CAPWAP_RUN_STATE);
						capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
					} else {
						result = CAPWAP_ERROR_CLOSE;
					}

					ac_soapclient_free_response(response);
				} else {
					result = CAPWAP_ERROR_CLOSE;
				}
			}

			break;
		}

		case AC_SESSION_ACTION_RECV_IEEE80211_MGMT_PACKET: {
			result = ac_session_action_recv_ieee80211_mgmt_packet(session, (struct capwap_header*)action->data, action->length);
			break;
		}

		case AC_SESSION_ACTION_NOTIFY_EVENT: {
			struct capwap_list_item* item;

			/* Copy event into queue */
			item = capwap_itemlist_create(sizeof(struct ac_session_notify_event_t));
			memcpy(item->item, action->data, sizeof(struct ac_session_notify_event_t));
			capwap_itemlist_insert_after(session->notifyevent, NULL, item);

			break;
		}

		case AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_ADD_STATION: {
			result = ac_session_action_station_configuration_ieee8011_add_station(session, (struct ac_notify_station_configuration_ieee8011_add_station*)action->data);
			break;
		}

		case AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_DELETE_STATION: {
			result = ac_session_action_station_configuration_ieee8011_delete_station(session, (struct ac_notify_station_configuration_ieee8011_delete_station*)action->data);
			break;
		}

		case AC_SESSION_ACTION_STATION_ROAMING: {
			struct ac_station* station;

			/* Delete station */
			station = ac_stations_get_station(session, RADIOID_ANY, NULL, (uint8_t*)action->data);
			if (station) {
				ac_stations_delete_station(session, station);
			}

			break;
		}
	}

	return result;
}
Ejemplo n.º 8
0
static int ac_backend_soap_waitevent(void) {
	int result = -1;
	struct ac_soap_request* request = NULL;
	struct ac_http_soap_server* server;
	struct json_object* jsonroot = NULL;

	ASSERT(g_ac_backend.soaprequest == NULL);
	ASSERT(g_ac_backend.backendsessionid != NULL);

	/* Get HTTP Soap Server */
	server = ac_backend_get_server();

	/* Critical section */
	capwap_lock_enter(&g_ac_backend.lock);

	/* Build Soap Request */
	if (!g_ac_backend.endthread) {
		request = ac_soapclient_create_request("waitBackendEvent", SOAP_NAMESPACE_URI);
		if (request) {
			ac_soapclient_add_param(request, "xs:string", "idsession", g_ac_backend.backendsessionid);
			g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server);

			/* Change result timeout */
			g_ac_backend.soaprequest->responsetimeout = SOAP_PROTOCOL_RESPONSE_WAIT_EVENT_TIMEOUT;
		}
	}

	capwap_lock_exit(&g_ac_backend.lock);

	/* */
	if (!g_ac_backend.soaprequest) {
		if (request) {
			ac_soapclient_free_request(request);
		}

		return -1;
	}

	/* Send Request & Recv Response */
	if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) {
		struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest);
		if (response) {
			/* Wait event result */
			jsonroot = ac_soapclient_parse_json_response(response);
			ac_soapclient_free_response(response);
		}
	}

	/* Critical section */
	capwap_lock_enter(&g_ac_backend.lock);

	/* Free resource */
	ac_soapclient_close_request(g_ac_backend.soaprequest, 1);
	g_ac_backend.soaprequest = NULL;

	capwap_lock_exit(&g_ac_backend.lock);

	/* Parsing JSON command after close event request */
	if (jsonroot) {
		if (json_object_get_type(jsonroot) == json_type_array) {
			int i;
			int length;

			/* Parsing every message into JSON result */
			length = json_object_array_length(jsonroot);
			if (!length) {
				result = 0;
			} else {
				for (i = 0; i < length; i++) {
					struct json_object* jsonitem = json_object_array_get_idx(jsonroot, i);
					if (jsonitem && (json_object_get_type(jsonitem) == json_type_object)) {
						result = ac_backend_parsing_event(jsonitem);
						if (result) {
							break;
						}
					}
				}
			}
		}

		/* Free JSON */
		json_object_put(jsonroot);
	}

	return result;
}
Ejemplo n.º 9
0
static int ac_backend_soap_join(int forcereset) {
	struct ac_soap_request* request = NULL;
	struct ac_http_soap_server* server;

	ASSERT(g_ac_backend.soaprequest == NULL);
	ASSERT(g_ac_backend.backendsessionid == NULL);

	/* Get HTTP Soap Server */
	server = ac_backend_get_server();

	/* Critical section */
	capwap_lock_enter(&g_ac_backend.lock);

	/* Build Soap Request */
	if (!g_ac_backend.endthread) {
		request = ac_soapclient_create_request("joinBackend", SOAP_NAMESPACE_URI);
		if (request) {
			ac_soapclient_add_param(request, "xs:string", "idac", g_ac.backendacid);
			ac_soapclient_add_param(request, "xs:string", "version", g_ac.backendversion);
			ac_soapclient_add_param(request, "xs:boolean", "forcereset", (forcereset ? "true" : "false"));
			g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server);
		}
	}

	capwap_lock_exit(&g_ac_backend.lock);

	/* */
	if (!g_ac_backend.soaprequest) {
		if (request) {
			ac_soapclient_free_request(request);
		}

		return -1;
	}

	/* Send Request & Recv Response */
	if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) {
		struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest);
		if (response) {
			/* Get join result */
			if ((response->responsecode == HTTP_RESULT_OK) && response->xmlResponseReturn) {
				xmlChar* xmlResult = xmlNodeGetContent(response->xmlResponseReturn);
				if (xmlStrlen(xmlResult)) {
					g_ac_backend.backendsessionid = capwap_duplicate_string((const char*)xmlResult);
				}

				xmlFree(xmlResult);
			}

			/* */
			ac_soapclient_free_response(response);
		}
	}

	/* Critical section */
	capwap_lock_enter(&g_ac_backend.lock);

	/* Free resource */
	ac_soapclient_close_request(g_ac_backend.soaprequest, 1);
	g_ac_backend.soaprequest = NULL;

	capwap_lock_exit(&g_ac_backend.lock);

	/* Retrieve AC configuration */
	if (g_ac_backend.backendsessionid && forcereset) {
		if (ac_backend_soap_getconfiguration()) {
			capwap_logging_error("Unable to get AC configuration from Backend Server");
			capwap_free(g_ac_backend.backendsessionid);
			g_ac_backend.backendsessionid = NULL;
		}
	}

	return (g_ac_backend.backendsessionid ? 0 : -1);
}
Ejemplo n.º 10
0
static int ac_backend_soap_getconfiguration(void) {
	int result = -1;
	struct ac_soap_request* request = NULL;
	struct ac_http_soap_server* server;
	struct json_object* jsonroot = NULL;

	ASSERT(g_ac_backend.soaprequest == NULL);
	ASSERT(g_ac_backend.backendsessionid != NULL);

	/* Get HTTP Soap Server */
	server = ac_backend_get_server();

	/* Critical section */
	capwap_lock_enter(&g_ac_backend.lock);

	/* Build Soap Request */
	if (!g_ac_backend.endthread) {
		request = ac_soapclient_create_request("getConfiguration", SOAP_NAMESPACE_URI);
		if (request) {
			ac_soapclient_add_param(request, "xs:string", "idsession", g_ac_backend.backendsessionid);
			g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server);
		}
	}

	capwap_lock_exit(&g_ac_backend.lock);

	/* */
	if (!g_ac_backend.soaprequest) {
		if (request) {
			ac_soapclient_free_request(request);
		}

		return -1;
	}

	/* Send Request & Recv Response */
	if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) {
		struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest);
		if (response) {
			/* Get Configuration result */
			jsonroot = ac_soapclient_parse_json_response(response);
			ac_soapclient_free_response(response);
		}
	}

	/* Critical section */
	capwap_lock_enter(&g_ac_backend.lock);

	/* Free resource */
	ac_soapclient_close_request(g_ac_backend.soaprequest, 1);
	g_ac_backend.soaprequest = NULL;

	capwap_lock_exit(&g_ac_backend.lock);

	/* Send JSON command to primary thread */
	if (jsonroot) {
		result = ac_msgqueue_update_configuration(jsonroot);
		if (result) {
			json_object_put(jsonroot);
		}
	}

	return result;
}
Ejemplo n.º 11
0
void ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
	unsigned short binding;
	struct ac_soap_response* response;
	struct capwap_header_data capwapheader;
	struct capwap_packet_txmng* txmngpacket;
	struct capwap_sessionid_element* sessionid;
	struct capwap_wtpboarddata_element* wtpboarddata;
	struct capwap_resultcode_element resultcode = { .code = CAPWAP_RESULTCODE_FAILURE };

	ASSERT(session != NULL);
	ASSERT(packet != NULL);

	/* Check binding */
	binding = GET_WBID_HEADER(packet->rxmngpacket->header);
	if (ac_valid_binding(binding)) {
		if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_JOIN_REQUEST) {
			/* Get sessionid and verify unique id */
			sessionid = (struct capwap_sessionid_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_SESSIONID);
			if (!ac_has_sessionid(sessionid)) {
				char* wtpid;

				/* Checking macaddress for detect if WTP already connected */
				wtpboarddata = (struct capwap_wtpboarddata_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPBOARDDATA);

				/* Get printable WTPID */
				wtpid = ac_get_printable_wtpid(wtpboarddata);
				if (wtpid && !ac_has_wtpid(wtpid)) {
					/* Request authorization of Backend for complete join */
					response = ac_soap_authorizewtpsession(session, wtpid);
					if (response) {
						resultcode.code = ac_dfa_state_join_check_authorizejoin(session, response);
						ac_soapclient_free_response(response);
					} else {
						resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE;
					}
				} else {
					capwap_logging_info("WTP Id %s already used in another session", wtpid);
					resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE;
				}

				/* */
				if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
					session->wtpid = wtpid;
					memcpy(&session->sessionid, sessionid, sizeof(struct capwap_sessionid_element));
					session->binding = binding;
				} else if (wtpid) {
					capwap_free(wtpid);
				}
			} else {
				char sessionname[33];

				capwap_sessionid_printf(sessionid, sessionname);
				capwap_logging_info("Session Id %s already used in another session", sessionname);

				resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_ID_ALREADY_IN_USE;
			}
		} else {
			resultcode.code = CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE;
		}
	} else {
		resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED;
	}

	/* Create response */
	capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, binding);
	txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_JOIN_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);

	/* */
	if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
		response = ac_dfa_state_join_parsing_request(session, packet);
		if (response) {
			resultcode.code = ac_dfa_state_join_create_response(session, packet, response, txmngpacket);
			ac_soapclient_free_response(response);
		}
	}

	/* Add always result code message element */
	capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);

	/* Join response complete, get fragment packets */
	ac_free_reference_last_response(session);
	capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid);
	if (session->responsefragmentpacket->count > 1) {
		session->fragmentid++;
	}

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

	/* Save remote sequence number */
	session->remotetype = packet->rxmngpacket->ctrlmsg.type;
	session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;

	/* Send Join response to WTP */
	if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->responsefragmentpacket)) {
		if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
			ac_dfa_change_state(session, CAPWAP_POSTJOIN_STATE);
			capwap_timeout_set(session->timeout, session->idtimercontrol, AC_JOIN_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
		} else {
			ac_session_teardown(session);
		}
	} else {
		/* Error to send packets */
		capwap_logging_debug("Warning: error to send join response packet");
		ac_session_teardown(session);
	}
}