int cw_out_generic(struct conn *conn, struct cw_action_out *a, uint8_t * dst) // ,struct mbag_item * item) { /* Get the item to put */ struct mbag_item *item = NULL; if (a->get) { item = a->get(conn, a); } /* Size for msg elem header depends on vendor specific payload */ int start = a->vendor_id ? 10 : 4; int len; if (!item) { const char *vendor=""; if ( a->vendor_id ) { vendor=cw_strvendor(a->vendor_id); } if (a->mand) { cw_log(LOG_ERR, "Can't put mandatory element %s%d - (%s) into %s. No value found.", vendor, a->elem_id, cw_strelemp(conn->actions, a->elem_id) , cw_strmsg(a->msg_id) ); } else{ cw_dbg(DBG_WARN,"No output for element %s%d -(%s) in %s. Item %s not found.", vendor, a->elem_id, cw_strelemp(conn->actions, a->elem_id) , cw_strmsg(a->msg_id),a->item_id); } return 0; } else { len = cw_put_item(dst + start, item); } if (a->vendor_id) return len + cw_put_elem_vendor_hdr(dst, a->vendor_id, a->elem_id, len); return len + cw_put_elem_hdr(dst, a->elem_id, len); }
int static check_len(struct conn *conn, struct cw_action_in *a, uint8_t * data, int len, struct sockaddr *from) { if (len < a->min_len) { cw_dbg(DBG_ELEM_ERR, "%d (%s) message element too short, len=%d, min len=%d", a->elem_id, cw_strelemp(conn->actions, a->elem_id), len, a->min_len); return 0; } if (len > a->max_len) { cw_dbg(DBG_ELEM_ERR, "%d (%s) message element too big, len=%d, max len=%d", a->elem_id, cw_strelemp(conn->actions, a->elem_id), len, a->max_len); return 0; } return 1; }
void cw_dbg_elem_colored(int level, struct conn *conn, int msg, int msgelem, const uint8_t * msgbuf, int len) { if (!cw_dbg_is_level(level)) return; const char *elemname; char vendorname[256]; char vendor_details[265]; *vendor_details = 0; if (msgelem == CW_ELEM_VENDOR_SPECIFIC_PAYLOAD) { uint32_t vendor_id = ntohl(*((uint32_t *) msgbuf)); int type = ntohs(*((uint16_t *) (msgbuf + 4))); cw_format_vendor(vendor_details, vendor_id, type, msgbuf); sprintf(vendorname, "%s/%s/%s", cw_strelemp(conn->actions, msgelem), (char *) cw_strvendor(vendor_id), vendor_details); elemname = vendorname; } else { elemname = cw_strelemp(conn->actions, msgelem); } if (!cw_dbg_is_level(DBG_ELEM_DMP)){ cw_dbg(DBG_ELEM, "%d (%s), len=%d", msgelem, elemname, len); } else{ char *dmp = cw_dbg_mkdmp(msgbuf,len); cw_dbg(DBG_ELEM, "%d (%s), len=%d%s%s", msgelem, elemname, len, get_dbg_color_ontext(DBG_ELEM_DMP), dmp); free(dmp); } }
/** * Put a list of missing mandatory message elements to debug output */ void cw_dbg_missing_mand(int level, struct conn *conn, cw_action_in_t ** ml, int n, cw_action_in_t * a) { // if (!cw_dbg_is_level(DBG_MSG_ERR) || n == 0) // return; if ( !cw_dbg_is_level(level) || n==0) return; char buffer[2000]; char *p = buffer; int i; char *delim = ""; for (i = 0; i < n; i++) { p += sprintf(p, "%s", delim); delim = ", "; p += sprintf(p, "%s", cw_strelemp(conn->actions, ml[i]->elem_id)); } cw_dbg(level, "Missing mandatory elements: [%s]", buffer); }
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); } }