Esempio n. 1
0
File: wtpman.c Progetto: 7u83/actube
int cw_run_state_machine(struct conn * conn, time_t *timer)
{

	int timerval;
	cw_StateMachineState_t search, *result;

	
	while(1){
		search.state = conn->capwap_state;
		search.prevstate = conn->capwap_prevstate;
		result = mavl_get(conn->msgset->state_machine,&search);
		
		cw_dbg(DBG_STATE,"State transition: [%s -> %s]",
			cw_strstate(conn->capwap_prevstate),
			cw_strstate(conn->capwap_state)
			);
		if (result == NULL){
			cw_log(LOG_ERR,"State not found");
			return 0;
		}
		if (result->jump_state){
			conn->capwap_state = result->jump_state;
			conn->capwap_prevstate = result->jump_prevstate;
			
			cw_dbg(DBG_STATE,"Jump to state: [%s->%s]",
				cw_strstate(conn->capwap_prevstate),
				cw_strstate(conn->capwap_state));
			continue;
		}
		
		if (result->dbgmsg){
			cw_dbg(DBG_STATE,"%s",result->dbgmsg);
		}
		
		if (result->timer_key){
			timerval = cw_ktv_get_word(conn->local_cfg,result->timer_key,result->timer_default);
			*timer = cw_timer_start(timerval);
			cw_dbg(DBG_STATE,"Starting timer: [%s] - %d seconds.",result->timer_key,timerval);
		}
		return result->retval;
	}
}
Esempio n. 2
0
static int process_elements(struct conn *conn, uint8_t * rawmsg, int len,
			    struct sockaddr *from)
{
	struct cw_action_in as, *af, *afm;

	int offset = cw_get_hdr_msg_offset(rawmsg);

	uint8_t *msg_ptr = rawmsg + offset;

	int elems_len = cw_get_msg_elems_len(msg_ptr);

	int payloadlen = len - offset;


	/* pre-check message */
	if (payloadlen - 8 != elems_len) {

		if (conn->strict_hdr) {
			cw_dbg(DBG_MSG_ERR,
			       "Discarding message from %s, msgelems len=%d, payload len=%d, (Strict CAPWAP) ",
			       sock_addr2str(&conn->addr), elems_len, payloadlen - 8);
			errno = EAGAIN;
			return -1;
		}


		if (elems_len < payloadlen - 8) {
			cw_dbg(DBG_RFC,
			       "Packet from from %s has %d bytes of extra data, ignoring.",
			       sock_addr2str(&conn->addr), payloadlen - 8 - elems_len);
			elems_len = len - 8;
		}

		if (elems_len > payloadlen - 8) {

			cw_dbg(DBG_RFC,
			       "Packet from from %s has msgelems len of %d bytes, but has only %d bytes of data, truncating.",
			       sock_addr2str(&conn->addr), elems_len, payloadlen - 8);
			elems_len = payloadlen - 8;
		}
	}



	if (!conn->detected) {
		//struct mod_ac *mod;
		struct cw_actiondef *ad = load_mods(conn, rawmsg, len, elems_len, from);
		if (!ad) {
			cw_log(LOG_ERR, "Error");
			errno = EAGAIN;
			return -1;
		}
		conn->actions = ad;
		conn->detected = 1;

	}



	/* prepare struct for search operation */
	as.capwap_state = conn->capwap_state;
	as.msg_id = cw_get_msg_id(msg_ptr);
	as.vendor_id = 0;
	as.elem_id = 0;
	as.proto = 0;


	/* Search for state/message combination */
	afm = cw_actionlist_in_get(conn->actions->in, &as);

	if (!afm) {
		/* Throw away unexpected response messages */
		if (!(as.msg_id & 1)) {
			cw_dbg(DBG_MSG_ERR,
			       "Message type %d (%s) unexpected/illegal in %s State, discarding.",
			       as.msg_id, cw_strmsg(as.msg_id),
			       cw_strstate(conn->capwap_state));
			errno = EAGAIN;
			return -1;
		}

		/* Request message not found in current state, check if we know 
		   anything else about this message type */
		const char *str = cw_strheap_get(conn->actions->strmsg, as.msg_id);
		int result_code = 0;
		if (str) {
			/* Message found, but it was in wrong state */
			cw_dbg(DBG_MSG_ERR,
			       "Message type %d (%s) not allowed in %s State.", as.msg_id,
			       cw_strmsg(as.msg_id), cw_strstate(as.capwap_state));
			result_code = CW_RESULT_MSG_INVALID_IN_CURRENT_STATE;
		} else {
			/* Message is unknown */
			cw_dbg(DBG_MSG_ERR, "Message type %d (%s) unknown.",
			       as.msg_id, cw_strmsg(as.msg_id),
			       cw_strstate(as.capwap_state));
			result_code = CW_RESULT_MSG_UNRECOGNIZED;

		}
		cw_send_error_response(conn, rawmsg, result_code);
		errno = EAGAIN;
		return -1;
	}

	
	if (conn->msg_start){
		conn->msg_start(conn, afm, rawmsg, len, from);
	}

	/* Execute start processor for message */
	if (afm->start) {
		afm->start(conn, afm, rawmsg, len, from);
	}

	uint8_t *elems_ptr = cw_get_msg_elems_ptr(msg_ptr);
	uint8_t *elem;

	/* Create an avltree to catch the found mandatory elements */
	conn->mand = stravltree_create();

	int unrecognized = 0;

	/* iterate through message elements */
	cw_foreach_elem(elem, elems_ptr, elems_len) {

		as.elem_id = cw_get_elem_id(elem);
		int elem_len = cw_get_elem_len(elem);


		af = cw_actionlist_in_get(conn->actions->in, &as);

		if (!af) {
			unrecognized++;
			cw_dbg(DBG_ELEM_ERR,
			       "Element %d (%s) not allowed in msg of type %d (%s), ignoring.",
			       as.elem_id, cw_strelemp(conn->actions, as.elem_id),
			       as.msg_id, cw_strmsg(as.msg_id));
			continue;
		}

		if (!check_len(conn, af, cw_get_elem_data(elem), elem_len, from)) {
			continue;
		}
		cw_dbg_elem(DBG_ELEM, conn, as.msg_id, as.elem_id, cw_get_elem_data(elem),
			    elem_len);



		int afrc = 1;
		if (af->start) {
			afrc =
			    af->start(conn, af, cw_get_elem_data(elem), elem_len, from);

		}

		if (af->mand && afrc) {
			/* add found mandatory message element 
			   to mand list */
			stravltree_add(conn->mand, af->item_id);
		}

		if(conn->elem_end){
			afrc = conn->elem_end(conn,af,afrc,cw_get_elem_data(elem), elem_len,from);
		}

	}