Better packet and message checking.

FossilOrigin-Name: 44468751ffdb24062b0ca793688ba4e9cb56625fdec79f1cb39cfbec4d96e9a7
This commit is contained in:
7u83@mail.ru 2015-04-12 14:57:00 +00:00
parent 8543d30bee
commit f1f5131735
1 changed files with 84 additions and 92 deletions

View File

@ -68,9 +68,13 @@ void cw_init_request(struct conn *conn, int msg_id)
{
uint8_t *buffer = conn->req_buffer;
/* zero the first 8 bytes */
cw_put_dword(buffer + 0, 0);
cw_put_dword(buffer + 4, 0);
cw_set_hdr_preamble(buffer, 0);
/* unencrypted */
cw_set_hdr_preamble(buffer, CAPWAP_VERSION << 4 | 0);
cw_set_hdr_hlen(buffer, 2);
cw_set_hdr_wbid(buffer, 1);
cw_set_hdr_rid(buffer, 0);
@ -122,37 +126,42 @@ int cw_send_error_response(struct conn *conn, uint8_t * rawmsg, uint32_t result_
}
static int cw_process_msg(struct conn *conn, uint8_t * rawmsg, int len)
static int process_elements(struct conn *conn, uint8_t * rawmsg, int len)
{
struct cw_action_in as, *af, *afm;
uint8_t *msg_ptr = rawmsg + cw_get_hdr_msg_offset(rawmsg);
int offset = cw_get_hdr_msg_offset(rawmsg);
uint8_t *msg_ptr = rawmsg + offset;
int elems_len = cw_get_msg_elems_len(msg_ptr);
/*
if (8+elems_len != len){
cw_dbg(DBG_MSG_ERR,"Discarding message from %s, msgelems len=%d, data len=%d, (strict capwap) ",
sock_addr2str(&conn->addr),elems_len,len-8);
if (conn_is_strict_capwap(conn)){
cw_dbg(DBG_MSG_ERR,"Discarding message from %s, msgelems len=%d, data len=%d, (strict capwap) ",
sock_addr2str(&conn->addr),elems_len,len-8);
return 0;
int payloadlen=len-offset;
/* pre-check message */
if (payloadlen-8 != elems_len ) {
if (conn_is_strict_capwap(conn)) {
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 (8+elems_len < len){
cw_dbg(DBG_CW_RFC,"Packet from from %s has %d bytes extra data.",
sock_addr2str(&conn->addr),len-8-elems_len);
elems_len=len-8;
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 (8+elems_len > len){
cw_dbg(DBG_CW_RFC,"Packet from from %s hass msgelems len of %d bytes but has only %d bytes of data, truncating.",
sock_addr2str(&conn->addr),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);
}
return 1;
}
*/
/* prepare struct for search operation */
@ -173,7 +182,7 @@ static int cw_process_msg(struct conn *conn, uint8_t * rawmsg, int len)
"Message type %d (%s) unexpected/illigal in %s State, discarding.",
as.msg_id, cw_strmsg(as.msg_id),
cw_strstate(conn->capwap_state));
errno=EAGAIN;
errno = EAGAIN;
return -1;
}
@ -217,28 +226,32 @@ static int cw_process_msg(struct conn *conn, uint8_t * rawmsg, int len)
as.elem_id = cw_get_elem_id(elem);
int elem_len = cw_get_elem_len(elem);
cw_dbg_elem(DBG_ELEM,conn, as.msg_id, as.elem_id, cw_get_elem_data(elem),
cw_dbg_elem(DBG_ELEM, conn, as.msg_id, as.elem_id, cw_get_elem_data(elem),
elem_len);
af = cw_actionlist_in_get(conn->actions->in, &as);
if (!af) {
cw_dbg(DBG_ELEM_ERR, "ELEM_ERR: Element %d (%s) not allowed in msg of type %d (%s).",
as.elem_id,cw_strelem(as.elem_id), as.msg_id, cw_strmsg(as.msg_id));
cw_dbg(DBG_ELEM_ERR,
"ELEM_ERR: Element %d (%s) not allowed in msg of type %d (%s).",
as.elem_id, cw_strelem(as.elem_id), as.msg_id,
cw_strmsg(as.msg_id));
continue;
}
if (af->mand) {
int afrc = 1;
if (af->start) {
afrc = af->start(conn, af, cw_get_elem_data(elem), elem_len);
}
if (af->mand && afrc) {
/* add found mandatory message element
to mand list */
intavltree_add(conn->mand, af->item_id);
}
if (af->start) {
af->start(conn, af, cw_get_elem_data(elem), elem_len);
}
}
int result_code = 0;
@ -256,10 +269,9 @@ static int cw_process_msg(struct conn *conn, uint8_t * rawmsg, int len)
/* regular response message */
cw_send_response(conn, rawmsg, len);
}
}
else{
} else {
/* whe have got a response message */
}
@ -286,8 +298,7 @@ static int process_message(struct conn *conn, uint8_t * rawmsg, int rawlen,
if (!(type & 0x1)) {
/* It's a response message, no further examination required. */
// cb(cbarg, rawmsg, rawlen);
return cw_process_msg(conn,rawmsg,rawlen);
return process_elements(conn, rawmsg, rawlen);
}
/* It's a request message, check if seqnum is right and if
@ -302,9 +313,7 @@ static int process_message(struct conn *conn, uint8_t * rawmsg, int rawlen,
if ((sd > 0 && sd < 128) || (sd < 0 && sd < -128) || s1 < 0) {
/* seqnum is ok, normal message processing */
conn->last_seqnum_received = seqnum;
return cw_process_msg(conn,rawmsg,rawlen);
//cb(cbarg, rawmsg, rawlen);
//return 0;
return process_elements(conn, rawmsg, rawlen);
}
if (sd != 0) {
@ -333,24 +342,30 @@ static int process_message(struct conn *conn, uint8_t * rawmsg, int rawlen,
cw_dbg(DBG_MSG_ERR, "Retransmitting response message to %s, seqnum=%d",
sock_addr2str(&conn->addr), s2);
// conn_send_cwmsg(conn, &conn->resp_msg);
// XXX untested
conn_send_msg(conn, conn->resp_buffer);
errno = EAGAIN;
return -1;
}
/*
* Process an incomming CAPWAP packet, assuming the packet is already decrypted
* @param pram conn conection object
* @param packet pointer to packet data
* @param len lenght of packet data
*/
int conn_process_packet(struct conn *conn, uint8_t * packet, int len)
{
/* show this packet in debug output */
cw_dbg_pkt(DBG_PKT_IN, conn, packet, len);
/* log this packet */
cw_dbg_pkt(DBG_PKT_IN,conn, packet, len);
if (len < 8) {
/* packet too short */
cw_dbg(DBG_PKT_ERR,
"Discarding packet from %s, packet too short, len=%d",
"Discarding packet from %s, packet too short, len=%d, at least 8 expected.",
sock_addr2str(&conn->addr), len);
errno = EAGAIN;
return -1;
@ -358,20 +373,21 @@ int conn_process_packet(struct conn *conn, uint8_t * packet, int len)
int preamble = cw_get_hdr_preamble(packet);
if ((preamble & 0xf0) != CW_VERSION) {
if ((preamble & 0xf0) != (CAPWAP_VERSION << 4)) {
/* wrong version */
cw_dbg(DBG_PKT_ERR,
"Discarding packet from %s, wrong version, version=%d",
sock_addr2str(&conn->addr), (preamble & 0xf0) >> 8);
errno=EAGAIN;
"Discarding packet from %s, wrong version, version=%d, version %d expected.",
sock_addr2str(&conn->addr), (preamble & 0xf0) >> 4,
CAPWAP_VERSION);
errno = EAGAIN;
return -1;
}
if (preamble & 0xf) {
/* dtls encoded, this shuold never happen here */
/* Encrypted data, this shuold never happen here */
cw_dbg(DBG_PKT_ERR,
"Discarding packet from %s, encrypted data, after encryption ...",
sock_addr2str(&conn->addr));
"Discarding packet from %s, encrypted data after decryption ...",
sock_addr2str(&conn->addr));
errno = EAGAIN;
return -1;
}
@ -382,70 +398,46 @@ int conn_process_packet(struct conn *conn, uint8_t * packet, int len)
int payloadlen = len - offs;
if (payloadlen < 0) {
/* Eleminate messages with wrong header size */
cw_dbg(DBG_PKT_ERR,
"Discarding packet from %s, header length greater than len, hlen=%d",
sock_addr2str(&conn->addr), offs);
/* EINVAL */
return 0;
"Discarding packet from %s, header length (%d) greater than packet len (%d).",
sock_addr2str(&conn->addr), offs, len);
errno = EAGAIN;
return -1;
}
/* Check Radio MAC if preset */
/* Check if Radio MAC is preset */
if (cw_get_hdr_flag_m(packet)) {
if (cw_get_hdr_rmac_len(packet) + 8 > offs) {
/* wrong rmac size */
cw_dbg(DBG_PKT_ERR,
"Discarding packet, wrong R-MAC size, size=%d",
*(packet + 8));
return 0;
"Discarding packet from %s, wrong R-MAC size, size=%d",
sock_addr2str(&conn->addr), *(packet + 8));
errno = EAGAIN;
return -1;
}
// memcpy(cwrmsg.rmac, packet+8,8);
}
// else{
// cwrmsg.rmac[0]=0;
// }
if (cw_get_hdr_flag_f(packet)) { /* fragmented */
if (cw_get_hdr_flag_f(packet)) {
/* fragmented, add the packet to fragman */
uint8_t *f;
f = fragman_add(conn->fragman, packet, offs, payloadlen);
if (f == NULL)
return 0;
// cw_dbg_packet(conn, f + 4, *(uint32_t *) f);
// extern int cw_process_msg(struct conn * conn,uint8_t*msg,int len);
// cw_process_msg(conn,f+4,*(uint32_t*)f);
//printf("Received a fragmented packetm should process it");
//exit(0);
/*
if (!cwrmsg_init_ctrlhdr(conn,&cwrmsg,f+4,*(uint32_t*)f)){
free(f);
return;
};
*/
cw_dbg_msg(DBG_MSG_IN, conn, packet, len);
int rc = process_message(conn, f + 4, *(uint32_t *) f, NULL, NULL);
free(f);
return rc;
}
//extern int cw_process_msg(struct conn * conn,uint8_t*msg,int len);
//cw_process_msg(conn,packet,len);
//if (!cwrmsg_init_ctrlhdr(conn,&cwrmsg,packet+hlen,len-hlen) ){
// cw_dbg(DBG_CW_PKT_ERR,"Discarding packet from %s, len=%d (too short)",sock_addr2str(&conn->addr));
// return;
//}
//msg_4*((val >> 19) & 0x1f);
cw_dbg_msg(DBG_MSG_IN,conn,packet,len);
return process_message(conn, packet, len, NULL,NULL);
/* not fragmented, we have a complete message */
cw_dbg_msg(DBG_MSG_IN, conn, packet, len);
return process_message(conn, packet, len, NULL, NULL);
}
@ -462,7 +454,7 @@ int cw_read_messages(struct conn *conn)
return n;
if (n > 0) {
// printf("Have a packet with %d bytes\n",n);
// printf("Have a packet with %d bytes\n",n);
return conn_process_packet(conn, buf, n);
}
//printf("DTLS_ERROR: %d\n",conn->dtls_error);