diff --git a/src/capwap/conn_process_packet.c b/src/capwap/conn_process_packet.c index 8c926708..56d366b8 100644 --- a/src/capwap/conn_process_packet.c +++ b/src/capwap/conn_process_packet.c @@ -22,32 +22,52 @@ #include "capwap.h" #include "cw_log.h" +#include "cw_util.h" + #include "conn.h" #include "sock.h" +#include //tube -static int cwrmsg_init_ctrlhdr(struct cwrmsg * cwrmsg, uint8_t * msg, int len) +static int cwrmsg_init_ctrlhdr(struct conn * conn, struct cwrmsg * cwrmsg, uint8_t * msg, int len) { - if (len<8) + if (len<8){ + cw_dbg(DBG_CW_PKT_ERR,"Discarding packet from %s, len=%d (too short)",sock_addr2str(&conn->addr),len); return 0; + } uint32_t val; - val = ntohl(*((uint32_t*)(msg+0))); - + /* first dword of header is the message type*/ cwrmsg->type = ntohl(*((uint32_t*)(msg))); - + /* second dword = seqnum, len and flags */ val = ntohl(*((uint32_t*)(msg+4))); - cwrmsg->seqnum = CW_GET_DWORD_BITS(val,0,8); - cwrmsg->msgelems_len=CW_GET_DWORD_BITS(val,8,16)-3; + + cwrmsg->seqnum = cw_get_dword_bits(val,0,8); + + cwrmsg->msgelems_len=cw_get_dword_bits(val,8,16)-3; + // ch->flags=CW_GET_DWORD_BITS(val,24,8); cwrmsg->msgelems=msg+8; if (8+cwrmsg->msgelems_len != len){ - return 0; - } + if (conn_is_strict_capwap(conn)){ + cw_dbg(DBG_CW_PKT_ERR,"Discarding packet from %s, msgelems len=%d, data len=%d, (strict capwap) ", + sock_addr2str(&conn->addr),cwrmsg->msgelems_len,len-8); + return 0; + } + if (8+cwrmsg->msgelems_len < len){ + cw_dbg(DBG_CW_RFC,"Packet from from %s has %d bytes extra data, ignoring.", + sock_addr2str(&conn->addr),len-8-cwrmsg->msgelems_len); + } + if (8+cwrmsg->msgelems_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),cwrmsg->msgelems_len,len-8); + } + return 1; + } return 1; } @@ -87,26 +107,58 @@ static int process_message(struct conn * conn,struct cwrmsg *cwrmsg,int (*cb)(vo /* the received request message was retransmitte by our peer, * let's retransmit our response message if we have one*/ - cw_dbg(DBG_CW_MSG_ERR,"Retransmitted request message from %s detected, seqnum=%d", - sock_addr2str(&conn->addr),s2); + cw_dbg(DBG_CW_MSG_ERR,"Retransmitted request message from %s detected, seqnum=%d, type=%d", + sock_addr2str(&conn->addr),s2,cwrmsg->type); - if (!conn->last_response){ - cw_dbg(DBG_CW_MSG_ERR,"No cached response for retransmission, request seqnum=%d",s2); + if (conn->resp_msg.type-1 != cwrmsg->type ){ + cw_dbg(DBG_CW_MSG_ERR,"No cached response for retransmission, request seqnum=%d,in cache=%d",s2,conn->resp_msg.type ); return 0; } cw_dbg(DBG_CW_MSG_ERR,"Retransmitting response message to %s, seqnum=%d", sock_addr2str(&conn->addr),s2); - conn_send_cwmsg(conn,conn->last_response); + conn_send_cwmsg(conn,&conn->resp_msg); return 1; } +#ifdef WITH_CW_LOG_DEBUG + +static void cw_dbg_packet(struct conn * conn, uint8_t * packet, int len) +{ + if (!cw_dbg_is_level(DBG_CW_PKT)) + return; + + /* print the header */ + char hdr[200]; + hdr_print(hdr,packet,len); + + + if (!cw_dbg_is_level(DBG_CW_PKT_DMP)){ + cw_dbg(DBG_CW_PKT,"Processing capwap packet from %s, len=%d\n%s",sock_addr2str(&conn->addr),len,hdr); + return; + + } + + cw_dbg_dmp(DBG_CW_PKT_DMP,packet,len,"Processing packet from %s, len=%d\n%s\n\tDump:", + sock_addr2str(&conn->addr),len,hdr + ); + + +} + +#else + #define cw_dbg_packet(...) +#endif + void conn_process_packet(struct conn * conn, uint8_t *packet, int len,int (*cb)(void*,struct cwrmsg*),void *cbarg) { - cw_dbg(DBG_CW_PKT_DTL,"Processing packet from %s, len=%d",sock_addr2str(&conn->addr),len); + cw_dbg_packet(conn,packet,len); + + + if (len<8){ /* packet too short */ @@ -119,7 +171,7 @@ void conn_process_packet(struct conn * conn, uint8_t *packet, int len,int (*cb)( int preamble = val >> 24; if ( (preamble & 0xf0) != CW_VERSION){ /* wrong version */ - cw_dbg(DBG_CW_PKT_ERR,"Discarding packet from %s, wrong version, version=%d",sock_addr2str(&conn->addr),preamble&0xf0); + cw_dbg(DBG_CW_PKT_ERR,"Discarding packet from %s, wrong version, version=%d",sock_addr2str(&conn->addr),(preamble&0xf0)>>8); return; } @@ -167,13 +219,19 @@ void conn_process_packet(struct conn * conn, uint8_t *packet, int len,int (*cb)( if (f==NULL) return; - cwrmsg_init_ctrlhdr(&cwrmsg,f+4,*(uint32_t*)f); + if (!cwrmsg_init_ctrlhdr(conn,&cwrmsg,f+4,*(uint32_t*)f)){ + free(f); + return; + }; process_message(conn,&cwrmsg,cb,cbarg); free (f); return; } - cwrmsg_init_ctrlhdr(&cwrmsg,packet+hlen,len-hlen); + 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; + } process_message(conn,&cwrmsg,cb,cbarg); return;