int capwap_out_capwap_control_ip_address(struct cw_ElemHandler * eh, struct cw_ElemHandlerParams * params, uint8_t * dst) { char key[CW_KTV_MAX_KEY_LEN]; int i; int wtps; cw_KTV_t * address; uint8_t *d; d = dst; i=0; do { /* uint8_t * msg;*/ int l; sprintf(key,"%s/address.%d",eh->key,i); address = cw_ktv_get(params->conn->local_cfg,key,CW_TYPE_IPADDRESS); sprintf(key,"%s/wtps.%d",eh->key,i); wtps = cw_ktv_get_word(params->conn->local_cfg,key,0); i++; if (address==NULL){ break; } /* msg = d;*/ l = address->type->len(address); switch(eh->id){ case CAPWAP_ELEM_CAPWAP_CONTROL_IPV4_ADDRESS: if (l!=4){ continue; } break; case CAPWAP_ELEM_CAPWAP_CONTROL_IPV6_ADDRESS: if (l!=16){ continue; } break; default: continue; } l = address->type->put(address,d+4); l+=cw_put_word(dst+4+l,wtps); l+=cw_put_elem_hdr(d,eh->id,l); cw_dbg_elem(DBG_ELEM_OUT,params->conn,params->msgdata->type,eh,d+4,l-4); d+=l; }while(address != NULL); return d-dst; }
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); } }