Esempio n. 1
0
struct capwap_timeout* capwap_timeout_init(void) {
	struct capwap_timeout* timeout;

	/* */
	timeout = (struct capwap_timeout*)capwap_alloc(sizeof(struct capwap_timeout));
	memset(timeout, 0, sizeof(struct capwap_timeout));

	/* */
	timeout->itemsreference = capwap_hash_create(CAPWAP_TIMEOUT_HASH_COUNT);
	timeout->itemsreference->item_gethash = capwap_timeout_hash_item_gethash;
	timeout->itemsreference->item_getkey = capwap_timeout_hash_item_getkey;
	timeout->itemsreference->item_cmp = capwap_timeout_hash_item_cmp;

	timeout->itemstimeout = capwap_list_create();

	return timeout;
}
Esempio n. 2
0
int ac_discovery_start(void) {
	int result;
	
	memset(&g_ac_discovery, 0, sizeof(struct ac_discovery_t));

	/* Init */
	capwap_event_init(&g_ac_discovery.waitpacket);
	capwap_lock_init(&g_ac_discovery.packetslock);
	g_ac_discovery.packets = capwap_list_create();

	/* Create thread */
	result = pthread_create(&g_ac_discovery.threadid, NULL, ac_discovery_thread, NULL);
	if (result) {
		capwap_logging_debug("Unable create discovery thread");
		return 0;
	}
	
	return 1;
}
Esempio n. 3
0
static void ac_send_invalid_request(struct ac_session_t* session, uint32_t errorcode) {
	struct capwap_header_data capwapheader;
	struct capwap_packet_txmng* txmngpacket;
	struct capwap_list* responsefragmentpacket;
	struct capwap_fragment_packet_item* packet;
	struct capwap_header* header;
	struct capwap_resultcode_element resultcode = { .code = errorcode };

	ASSERT(session != NULL);
	ASSERT(session->rxmngpacket != NULL);
	ASSERT(session->rxmngpacket->fragmentlist->first != NULL);

	/* */
	packet = (struct capwap_fragment_packet_item*)session->rxmngpacket->fragmentlist->first->item;
	header = (struct capwap_header*)packet->buffer;

	/* Odd message type */
	capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(header));
	txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, session->rxmngpacket->ctrlmsg.type + 1, session->rxmngpacket->ctrlmsg.seq, session->mtu);

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

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

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

	/* Send unknown response */
	capwap_crypt_sendto_fragmentpacket(&session->dtls, responsefragmentpacket);

	/* Don't buffering a packets sent */
	capwap_list_free(responsefragmentpacket);
}
Esempio n. 4
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;
}
Esempio n. 5
0
static struct capwap_packet_txmng* ac_create_discovery_response(struct capwap_parsed_packet* packet) {
	int i;
	unsigned short binding;
	struct capwap_list* controllist;
	struct capwap_list_item* item;
	struct capwap_header_data capwapheader;
	struct capwap_packet_txmng* txmngpacket;

	/* Check is valid binding */
	binding = GET_WBID_HEADER(packet->rxmngpacket->header);
	if (!ac_valid_binding(binding)) {
		return NULL;
	}

	/* Update statistics */
	ac_update_statistics();

	/* Build packet */
	capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, binding);
	txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_DISCOVERY_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, g_ac.mtu);

	/* Prepare discovery response */
	capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACDESCRIPTION, &g_ac.descriptor);
	capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACNAME, &g_ac.acname);
	if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
		struct capwap_array* wtpradioinformation = (struct capwap_array*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION);

		for (i = 0; i < wtpradioinformation->count; i++) {
			struct capwap_80211_wtpradioinformation_element* radio;

			radio = *(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(wtpradioinformation, i);
			capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, radio);
		}
	}

	/* Get information from any local address */
	controllist = capwap_list_create();
	ac_get_control_information(controllist);

	for (item = controllist->first; item != NULL; item = item->next) {
		struct ac_session_control* sessioncontrol = (struct ac_session_control*)item->item;
	
		if (sessioncontrol->localaddress.ss.ss_family == AF_INET) {
			struct capwap_controlipv4_element element;

			memcpy(&element.address, &((struct sockaddr_in*)&sessioncontrol->localaddress)->sin_addr, sizeof(struct in_addr));
			element.wtpcount = sessioncontrol->count;
			capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV4, &element);
		} else if (sessioncontrol->localaddress.ss.ss_family == AF_INET6) {
			struct capwap_controlipv6_element element;

			memcpy(&element.address, &((struct sockaddr_in6*)&sessioncontrol->localaddress)->sin6_addr, sizeof(struct in6_addr));
			element.wtpcount = sessioncontrol->count;
			capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV6, &element);
		}
	}

	capwap_list_free(controllist);

	/* CAPWAP_ELEMENT_VENDORPAYLOAD */					/* TODO */

	return txmngpacket;
}
Esempio n. 6
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);
	}
}
Esempio n. 7
0
static uint32_t ac_dfa_state_join_create_response(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct ac_soap_response* response, struct capwap_packet_txmng* txmngpacket) {
	int i;
	int j;
	int length;
	struct json_object* jsonroot;
	struct json_object* jsonelement;
	struct capwap_list* controllist;
	struct capwap_list_item* item;
	unsigned short binding = GET_WBID_HEADER(packet->rxmngpacket->header);

	/* Receive SOAP response with JSON result
		{
			WTPRadioInformation: [
				<IEEE 802.11 BINDING>
				IEEE80211WTPRadioInformation: {
					RadioID: [int],
					Mode: [int]
				}
			]
			ACIPv4List: [
				{
					ACIPAddress: [string]
				}
			],
			ACIPv6List: [
				{
					ACIPAddress: [string]
				}
			]
			<IEEE 802.11 BINDING>
			WTPRadio: [
				{
					RadioID: [int],
					IEEE80211WTPRadioInformation: {
						Mode: [int]
					}
				}
			]
		}
	*/

	/* Add message elements response, every local value can be overwrite from backend server */
	jsonroot = ac_soapclient_parse_json_response(response);
	if (!jsonroot) {
		return CAPWAP_RESULTCODE_FAILURE;
	}

	/* AC Descriptor */
	ac_update_statistics();
	capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACDESCRIPTION, &g_ac.descriptor);

	/* AC Name */
	capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACNAME, &g_ac.acname);

	/* WTP Radio Information */
	if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
		struct ac_json_ieee80211_wtpradio wtpradio;
		struct capwap_array* wtpradioinformation = (struct capwap_array*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION);

		/* */
		ac_json_ieee80211_init(&wtpradio);

		/* */
		jsonelement = compat_json_object_object_get(jsonroot, IEEE80211_BINDING_JSON_ROOT);
		if (jsonelement) {
			ac_json_ieee80211_parsingjson(&wtpradio, jsonelement);
		}

		/* Copy WTP Radio Information if not present into SOAP response */
		for (i = 0; i < wtpradioinformation->count; i++) {
			ac_json_ieee80211_addmessageelement(&wtpradio, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, *(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(wtpradioinformation, i), 0);
		}

		/* */
		ac_json_ieee80211_buildpacket(&wtpradio, txmngpacket);

		/* Free resource */
		ac_json_ieee80211_free(&wtpradio);
	}

	/* ECN Support */
	capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ECNSUPPORT, &session->dfa.ecn);

	/* Get information from any local address */
	controllist = capwap_list_create();
	ac_get_control_information(controllist);

	/* CAPWAP Control IP Address */
	for (item = controllist->first; item != NULL; item = item->next) {
		struct ac_session_control* sessioncontrol = (struct ac_session_control*)item->item;

		if (sessioncontrol->localaddress.ss.ss_family == AF_INET) {
			struct capwap_controlipv4_element element;

			memcpy(&element.address, &((struct sockaddr_in*)&sessioncontrol->localaddress)->sin_addr, sizeof(struct in_addr));
			element.wtpcount = sessioncontrol->count;
			capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV4, &element);
		} else if (sessioncontrol->localaddress.ss.ss_family == AF_INET6) {
			struct capwap_controlipv6_element element;

			memcpy(&element.address, &((struct sockaddr_in6*)&sessioncontrol->localaddress)->sin6_addr, sizeof(struct in6_addr));
			element.wtpcount = sessioncontrol->count;
			capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV6, &element);
		}
	}

	capwap_list_free(controllist);

	/* CAPWAP Local IP Address */
	if (session->dtls.localaddr.ss.ss_family == AF_INET) {
		struct capwap_localipv4_element addr;

		memcpy(&addr.address, &session->dtls.localaddr.sin.sin_addr, sizeof(struct in_addr));
		capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_LOCALIPV4, &addr);
	} else if (session->dtls.localaddr.ss.ss_family == AF_INET6) {
		struct capwap_localipv6_element addr;

		memcpy(&addr.address, &session->dtls.localaddr.sin6.sin6_addr, sizeof(struct in6_addr));
		capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_LOCALIPV6, &addr);
	}

	/* ACIPv4List */
	jsonelement = NULL;
	if (jsonroot) {
		jsonelement = compat_json_object_object_get(jsonroot, "ACIPv4List");
		if (jsonelement && (json_object_get_type(jsonelement) == json_type_array)) {
			length = json_object_array_length(jsonelement);
		} else {
			jsonelement = NULL;
		}
	}

	if (jsonelement) {
		struct capwap_acipv4list_element* responseacipv4list;

		responseacipv4list = (struct capwap_acipv4list_element*)capwap_alloc(sizeof(struct capwap_acipv4list_element));
		responseacipv4list->addresses = capwap_array_create(sizeof(struct in_addr), 0, 0);

		for (j = 0; j < length; j++) {
			struct json_object* jsonvalue = json_object_array_get_idx(jsonelement, j);
			if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) {
				struct json_object* jsonitem;

				/* ACIPAddress */
				jsonitem = compat_json_object_object_get(jsonvalue, "ACIPAddress");
				if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) {
					const char* value = json_object_get_string(jsonitem);
					if (value) {
						union sockaddr_capwap address;
						if (capwap_address_from_string(value, &address)) {
							/* Accept only IPv4 address */
							if (address.ss.ss_family == AF_INET) {
								struct in_addr* responseaddress_in = (struct in_addr*)capwap_array_get_item_pointer(responseacipv4list->addresses, responseacipv4list->addresses->count);
								memcpy(responseaddress_in, &address.sin.sin_addr, sizeof(struct in_addr));
							}
						}
					}
				}
			}
		}

		if (responseacipv4list->addresses->count > 0) {
			capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV4LIST, responseacipv4list);
		}

		capwap_array_free(responseacipv4list->addresses);
		capwap_free(responseacipv4list);
	} else if (session->dfa.acipv4list.addresses->count > 0) {
		capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV4LIST, &session->dfa.acipv4list);
	}

	/* ACIPv6List */
	jsonelement = NULL;
	if (jsonroot) {
		jsonelement = compat_json_object_object_get(jsonroot, "ACIPv6List");
		if (jsonelement && (json_object_get_type(jsonelement) == json_type_array)) {
			length = json_object_array_length(jsonelement);
		} else {
			jsonelement = NULL;
		}
	}

	if (jsonelement) {
		int j;
		struct capwap_acipv6list_element* responseacipv6list;

		responseacipv6list = (struct capwap_acipv6list_element*)capwap_alloc(sizeof(struct capwap_acipv6list_element));
		responseacipv6list->addresses = capwap_array_create(sizeof(struct in6_addr), 0, 0);

		for (j = 0; j < length; j++) {
			struct json_object* jsonvalue = json_object_array_get_idx(jsonelement, j);
			if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) {
				struct json_object* jsonitem;

				/* ACIPAddress */
				jsonitem = compat_json_object_object_get(jsonvalue, "ACIPAddress");
				if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) {
					const char* value = json_object_get_string(jsonitem);
					if (value) {
						union sockaddr_capwap address;
						if (capwap_address_from_string(value, &address)) {
							/* Accept only IPv6 address */
							if (address.ss.ss_family == AF_INET6) {
								struct in6_addr* responseaddress_in6 = (struct in6_addr*)capwap_array_get_item_pointer(responseacipv6list->addresses, responseacipv6list->addresses->count);
								memcpy(responseaddress_in6, &address.sin6.sin6_addr, sizeof(struct in6_addr));
							}
						}
					}
				}
			}
		}

		if (responseacipv6list->addresses->count > 0) {
			capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV6LIST, responseacipv6list);
		}

		capwap_array_free(responseacipv6list->addresses);
		capwap_free(responseacipv6list);
	} else if (session->dfa.acipv6list.addresses->count > 0) {
		capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV6LIST, &session->dfa.acipv6list);
	}

	/* CAPWAP Transport Protocol */
	capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_TRANSPORT, &session->dfa.transport);

	/* CAPWAP_ELEMENT_IMAGEIDENTIFIER */				/* TODO */
	/* CAPWAP_ELEMENT_MAXIMUMLENGTH */					/* TODO */
	/* CAPWAP_ELEMENT_VENDORPAYLOAD */					/* TODO */

	if (jsonroot) {
		json_object_put(jsonroot);
	}

	return CAPWAP_RESULTCODE_SUCCESS;
}
Esempio n. 8
0
/* Create new session */
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(sock >= 0);
	ASSERT(fromaddr != NULL);
	ASSERT(toaddr != NULL);

	/* Create new session */
	itemlist = capwap_itemlist_create(sizeof(struct ac_session_t));
	session = (struct ac_session_t*)itemlist->item;
	memset(session, 0, sizeof(struct ac_session_t));

	session->itemlist = itemlist;
	session->running = 1;

	/* */
	capwap_crypt_setconnection(&session->dtls, sock, toaddr, fromaddr);

	/* */
	ac_wlans_init(session);

	/* */
	session->count = 2;
	capwap_event_init(&session->changereference);

	/* */
	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);
	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 */
	capwap_event_init(&session->waitpacket);
	capwap_lock_init(&session->sessionlock);

	session->action = capwap_list_create();
	session->packets = capwap_list_create();
	session->requestfragmentpacket = capwap_list_create();
	session->responsefragmentpacket = capwap_list_create();
	session->notifyevent = capwap_list_create();

	session->mtu = g_ac.mtu;
	session->state = CAPWAP_IDLE_STATE;

	/* Update session list */
	capwap_rwlock_wrlock(&g_ac.sessionslock);
	capwap_itemlist_insert_after(g_ac.sessions, NULL, itemlist);
	capwap_rwlock_unlock(&g_ac.sessionslock);

	/* Create thread */
	result = pthread_create(&session->threadid, NULL, ac_session_thread, (void*)session);
	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 = session->threadid;

		/* */
		capwap_itemlist_insert_after(g_ac.sessionsthread, NULL, itemlist);
	} else {
		capwap_logging_fatal("Unable create session thread, error code %d", result);
		capwap_exit(CAPWAP_OUT_OF_MEMORY);
	}

	return session;
}