Ejemplo n.º 1
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.º 2
0
int capwap_parsing_packet(struct capwap_packet_rxmng* rxmngpacket, struct capwap_parsed_packet* packet) {
	unsigned short binding;
	unsigned short bodylength;

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

	/* */
	memset(packet, 0, sizeof(struct capwap_parsed_packet));
	packet->rxmngpacket = rxmngpacket;
	packet->messages = capwap_list_create();

	binding = GET_WBID_HEADER(packet->rxmngpacket->header);

	/* Position reader to capwap body */
	memcpy(&rxmngpacket->readpos, &rxmngpacket->readbodypos, sizeof(struct read_block_from_pos));

	/* */
	bodylength = rxmngpacket->ctrlmsg.length - CAPWAP_CONTROL_MESSAGE_MIN_LENGTH;
	while (bodylength > 0) {
		struct capwap_message_element_id id = { .vendor = 0 };
		uint16_t msglength;
		struct capwap_list_item* itemlist;
		struct capwap_message_element_itemlist* messageelement;
		void *element;
		const struct capwap_message_elements_ops* read_ops;

		/* Get type and length */
		rxmngpacket->readerpacketallowed = sizeof(struct capwap_message_element);
		if (rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &id.type) != sizeof(uint16_t) ||
		    rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &msglength) != sizeof(uint16_t) ||
		    msglength > bodylength)
			return INVALID_MESSAGE_ELEMENT;

		/* Allowed to parsing only the size of message element */
		rxmngpacket->readerpacketallowed = msglength;

		/* Check binding */
		if (IS_80211_MESSAGE_ELEMENTS(id) &&
		    (binding != CAPWAP_WIRELESS_BINDING_IEEE80211))
			return UNRECOGNIZED_MESSAGE_ELEMENT;

		log_printf(LOG_DEBUG, "MESSAGE ELEMENT: %d", id.type);

		if (id.type == CAPWAP_ELEMENT_VENDORPAYLOAD_TYPE) {
			struct capwap_message_element_id vendor_id;

			if (msglength < 7) {
				log_printf(LOG_DEBUG, "Invalid Vendor Specific Payload element: underbuffer");
				return INVALID_MESSAGE_ELEMENT;
			}
			if ((msglength - 6) > CAPWAP_VENDORPAYLOAD_MAXLENGTH) {
				log_printf(LOG_DEBUG, "Invalid Vendor Specific Payload element: overbuffer");
				return INVALID_MESSAGE_ELEMENT;
			}

			rxmngpacket->read_ops.read_u32((capwap_message_elements_handle)rxmngpacket, &vendor_id.vendor);
			rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &vendor_id.type);

			log_printf(LOG_DEBUG, "VENDOR MESSAGE ELEMENT: %06x:%d", vendor_id.vendor, vendor_id.type);

			read_ops = capwap_get_message_element_ops(vendor_id);
			log_printf(LOG_DEBUG, "vendor read_ops: %p", read_ops);
			if (read_ops) {
				id = vendor_id;
				element = read_ops->parse((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->read_ops);
			} else {
				read_ops = capwap_get_message_element_ops(id);
				element = capwap_unknown_vendorpayload_element_parsing((capwap_message_elements_handle)rxmngpacket,
										       &rxmngpacket->read_ops, msglength - 6, vendor_id);
			}
		} else {
			/* Reader function */
			read_ops = capwap_get_message_element_ops(id);
			log_printf(LOG_DEBUG, "read_ops: %p", read_ops);

			if (!read_ops)
				return UNRECOGNIZED_MESSAGE_ELEMENT;

			/* Get message element */
			element = read_ops->parse((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->read_ops);
		}

		if (!element)
			return INVALID_MESSAGE_ELEMENT;

		/* */
		itemlist = capwap_get_message_element(packet, id);
		if (read_ops->category == CAPWAP_MESSAGE_ELEMENT_SINGLE) {
			/* Check for multiple message element */
			if (itemlist) {
				return INVALID_MESSAGE_ELEMENT;
			}

			/* Create new message element */
			itemlist = capwap_itemlist_create(sizeof(struct capwap_message_element_itemlist));
			messageelement = (struct capwap_message_element_itemlist*)itemlist->item;
			messageelement->id = id;
			messageelement->category = CAPWAP_MESSAGE_ELEMENT_SINGLE;
			messageelement->data = element;

			/* */
			capwap_itemlist_insert_after(packet->messages, NULL, itemlist);
		}
		else if (read_ops->category == CAPWAP_MESSAGE_ELEMENT_ARRAY) {
			struct capwap_array* arraymessageelement;

			if (itemlist) {
				messageelement = (struct capwap_message_element_itemlist*)itemlist->item;
				arraymessageelement = (struct capwap_array*)messageelement->data;
			} else {
				arraymessageelement = capwap_array_create(sizeof(void*), 0, 0);

				/* */
				itemlist = capwap_itemlist_create(sizeof(struct capwap_message_element_itemlist));
				messageelement = (struct capwap_message_element_itemlist*)itemlist->item;
				messageelement->id = id;
				messageelement->category = CAPWAP_MESSAGE_ELEMENT_ARRAY;
				messageelement->data = (void*)arraymessageelement;

				/* */
				capwap_itemlist_insert_after(packet->messages, NULL, itemlist);
			}

			/* */
			*(void **)capwap_array_get_item_pointer(arraymessageelement, arraymessageelement->count) = element;
		}

		/* Check if read all data of message element */
		if (rxmngpacket->readerpacketallowed) {
			return INVALID_MESSAGE_ELEMENT;
		}

		/* */
		bodylength -= (msglength + sizeof(struct capwap_message_element));
	}

	return PARSING_COMPLETE;
}

/* */
int capwap_validate_parsed_packet(struct capwap_parsed_packet* packet, struct capwap_array* returnedmessage) {
	unsigned short binding;
	struct capwap_resultcode_element* resultcode;

	ASSERT(packet != NULL);
	ASSERT(packet->rxmngpacket != NULL);

	binding = GET_WBID_HEADER(packet->rxmngpacket->header);

	switch (packet->rxmngpacket->ctrlmsg.type) {
		case CAPWAP_DISCOVERY_REQUEST: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_DISCOVERYTYPE) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPBOARDDATA) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPDESCRIPTOR) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFRAMETUNNELMODE) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPMACTYPE)) {

				if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
					if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION)) {
						return 0;
					}
				} else {
					return 0;
				}
			}

			break;
		}

		case CAPWAP_DISCOVERY_RESPONSE: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ACDESCRIPTION) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAME) &&
				(capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV6))) {
				return 0;
			}

			/* Check if packet contains Result Code with Error Message */
			resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
			if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
				return 0;
			}

			break;
		}

		case CAPWAP_JOIN_REQUEST: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCATION) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPBOARDDATA) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPDESCRIPTOR) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPNAME) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_SESSIONID) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFRAMETUNNELMODE) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPMACTYPE) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_ECNSUPPORT) &&
				(capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCALIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCALIPV6))) {

				if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
					if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION)) {
						return 0;
					}
				} else {
					return 0;
				}
			}

			break;
		}

		case CAPWAP_JOIN_RESPONSE: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_ACDESCRIPTION) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAME) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_ECNSUPPORT) &&
				(capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV6)) &&
				(capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCALIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCALIPV6))) {
				return 0;
			}

			/* Check if packet contains Result Code with Error Message */
			resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
			if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
				return 0;
			}

			break;
		}

		case CAPWAP_CONFIGURATION_STATUS_REQUEST: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAME) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_RADIOADMSTATE) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_STATISTICSTIMER) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPREBOOTSTAT)) {

				if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
					if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION)) {
						return 0;
					}
				} else {
					return 0;
				}
			}

			break;
		}

		case CAPWAP_CONFIGURATION_STATUS_RESPONSE: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_TIMERS) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_IDLETIMEOUT) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFALLBACK) &&
				(capwap_get_message_element(packet, CAPWAP_ELEMENT_ACIPV4LIST) || capwap_get_message_element(packet, CAPWAP_ELEMENT_ACIPV6LIST))) {

				return 0;
			}

			/* Check if packet contains Result Code with Error Message */
			resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
			if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
				return 0;
			}

			break;
		}

		case CAPWAP_CONFIGURATION_UPDATE_REQUEST: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAMEPRIORITY) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_ACTIMESTAMP) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_ADDMACACL) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_TIMERS) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_DELETEMACACL) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_IDLETIMEOUT) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCATION) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_RADIOADMSTATE) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_STATISTICSTIMER) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFALLBACK) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPNAME) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPSTATICIPADDRESS) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_IMAGEIDENTIFIER) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_VENDORPAYLOAD)) {

				return 0;
			}

			break;
		}

		case CAPWAP_CONFIGURATION_UPDATE_RESPONSE: {
			return 0;
		}

		case CAPWAP_WTP_EVENT_REQUEST: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_DUPLICATEIPV4) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_DUPLICATEIPV6) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPRADIOSTAT) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPREBOOTSTAT) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_DELETESTATION) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_VENDORPAYLOAD)) {

				return 0;
			}

			break;
		}

		case CAPWAP_WTP_EVENT_RESPONSE: {
			return 0;
		}

		case CAPWAP_CHANGE_STATE_EVENT_REQUEST: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RADIOOPRSTATE) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) {

				return 0;
			}

			break;
		}

		case CAPWAP_CHANGE_STATE_EVENT_RESPONSE: {
			return 0;
		}

		case CAPWAP_ECHO_REQUEST: {
			return 0;
		}

		case CAPWAP_ECHO_RESPONSE: {
			return 0;
		}

		case CAPWAP_IMAGE_DATA_REQUEST: {
			return 0;
		}

		case CAPWAP_IMAGE_DATA_RESPONSE: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) {
				return 0;
			}

			break;
		}

		case CAPWAP_RESET_REQUEST: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_IMAGEIDENTIFIER)) {
				return 0;
			}

			break;
		}

		case CAPWAP_RESET_RESPONSE: {
			return 0;
		}

		case CAPWAP_PRIMARY_DISCOVERY_REQUEST: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_DISCOVERYTYPE) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPBOARDDATA) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPDESCRIPTOR) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFRAMETUNNELMODE) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPMACTYPE)) {

				if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
					if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION)) {
						return 0;
					}
				} else {
					return 0;
				}
			}

			break;
		}

		case CAPWAP_PRIMARY_DISCOVERY_RESPONSE: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ACDESCRIPTION) &&
				capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAME) &&
				(capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV6))) {
				return 0;
			}

			/* Check if packet contains Result Code with Error Message */
			resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
			if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
				return 0;
			}

			break;
		}

		case CAPWAP_DATA_TRANSFER_REQUEST: {
			/* TODO */
			break;
		}

		case CAPWAP_DATA_TRANSFER_RESPONSE: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) {
				return 0;
			}

			break;
		}

		case CAPWAP_CLEAR_CONFIGURATION_REQUEST: {
			return 0;
		}

		case CAPWAP_CLEAR_CONFIGURATION_RESPONSE: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) {
				return 0;
			}

			break;
		}

		case CAPWAP_STATION_CONFIGURATION_REQUEST: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ADDSTATION)) {
				if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
					if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_STATION)) {
						return 0;
					}
				} else {
					return 0;
				}
			} else if (capwap_get_message_element(packet, CAPWAP_ELEMENT_DELETESTATION)) {
				return 0;
			}

			break;
		}

		case CAPWAP_STATION_CONFIGURATION_RESPONSE: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) {
				return 0;
			}

			break;
		}

		case CAPWAP_IEEE80211_WLAN_CONFIGURATION_REQUEST: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_ADD_WLAN) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_UPDATE_WLAN) ||
				capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_DELETE_WLAN)) {

				return 0;
			}

			break;
		}

		case CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE: {
			if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) {
				return 0;
			}

			break;
		}
	}

	return -1;
}
Ejemplo n.º 3
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);
	}
}