victor must be getting sick of PPPoE and ICMP

remotes/origin/master-1.0.x
Jamie 17 years ago committed by Victor Julien
parent b6deadd2b4
commit a297225157

@ -19,6 +19,11 @@ enum {
IPV4_OPT_DUPLICATE,
IPV4_OPT_UNKNOWN,
/* ICMP EVENTS */
ICMPV4_PKT_TOO_SMALL,
ICMPV4_UNKNOWN_TYPE,
ICMPV4_UNKNOWN_CODE,
/* IPV6 EVENTS */
IPV6_PKT_TOO_SMALL,
IPV6_TRUNC_PKT,
@ -62,6 +67,8 @@ enum {
/* PPPOE EVENTS */
PPPOE_PKT_TOO_SMALL,
PPPOE_WRONG_CODE,
PPPOE_MALFORMED_TAGS,
/* GRE EVENTS */
GRE_PKT_TOO_SMALL,

@ -2,6 +2,7 @@
#include "eidps-common.h"
#include "decode.h"
#include "decode-events.h"
#include "decode-icmpv4.h"
#include "util-unittest.h"
@ -57,6 +58,14 @@ inline uint16_t ICMPV4CalculateChecksum(uint16_t *pkt, uint16_t tlen)
return (uint16_t) ~csum;
}
/**
* \todo
* Note, this is the IP header, plus a bit of the original packet, not the whole thing!
*/
void DecodePartialIPV4( uint8_t* partial_packet, uint16_t len )
{
}
/** DecodeICMPV4
* \brief Main ICMPv4 decoding function
*/
@ -65,7 +74,7 @@ void DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
PerfCounterIncr(dtv->counter_icmpv4, tv->pca);
if (len < ICMPV4_HEADER_LEN) {
/** \todo decode event */
DECODER_SET_EVENT(p,ICMPV4_PKT_TOO_SMALL);
return;
}
@ -77,6 +86,129 @@ void DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
p->proto = IPPROTO_ICMP;
ICMPV4ExtHdr* icmp4eh = (ICMPV4ExtHdr*) p->icmpv4h;
switch (p->icmpv4h->type)
{
case ICMP_ECHOREPLY:
p->icmpv4vars.id=icmp4eh->id;
p->icmpv4vars.seq=icmp4eh->seq;
if (p->icmpv4h->code!=0) {
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
}
break;
case ICMP_DEST_UNREACH:
if (p->icmpv4h->code>ICMP_SR_FAILED) {
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
} else {
// parse IP header plus 64 bytes
if (len >= ICMPV4_HEADER_PKT_OFFSET)
DecodePartialIPV4( (uint8_t*) (p->icmpv4h + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
}
break;
case ICMP_SOURCE_QUENCH:
if (p->icmpv4h->code!=0) {
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
} else {
// parse IP header plus 64 bytes
if (len >= ICMPV4_HEADER_PKT_OFFSET)
DecodePartialIPV4( (uint8_t*) (p->icmpv4h + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
}
break;
case ICMP_REDIRECT:
if (p->icmpv4h->code>ICMP_REDIR_HOSTTOS) {
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
} else {
// parse IP header plus 64 bytes
if (len >= ICMPV4_HEADER_PKT_OFFSET)
DecodePartialIPV4( (uint8_t*) (p->icmpv4h + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
}
break;
case ICMP_ECHO:
p->icmpv4vars.id=icmp4eh->id;
p->icmpv4vars.seq=icmp4eh->seq;
if (p->icmpv4h->code!=0) {
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
}
break;
case ICMP_TIME_EXCEEDED:
if (p->icmpv4h->code>ICMP_EXC_FRAGTIME) {
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
} else {
// parse IP header plus 64 bytes
if (len >= ICMPV4_HEADER_PKT_OFFSET)
DecodePartialIPV4( (uint8_t*) (p->icmpv4h + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
}
break;
case ICMP_PARAMETERPROB:
if (p->icmpv4h->code!=0) {
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
} else {
// parse IP header plus 64 bytes
if (len >= ICMPV4_HEADER_PKT_OFFSET)
DecodePartialIPV4( (uint8_t*) (p->icmpv4h + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
}
break;
case ICMP_TIMESTAMP:
p->icmpv4vars.id=icmp4eh->id;
p->icmpv4vars.seq=icmp4eh->seq;
if (p->icmpv4h->code!=0) {
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
}
break;
case ICMP_TIMESTAMPREPLY:
p->icmpv4vars.id=icmp4eh->id;
p->icmpv4vars.seq=icmp4eh->seq;
if (p->icmpv4h->code!=0) {
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
}
break;
case ICMP_INFO_REQUEST:
p->icmpv4vars.id=icmp4eh->id;
p->icmpv4vars.seq=icmp4eh->seq;
if (p->icmpv4h->code!=0) {
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
}
break;
case ICMP_INFO_REPLY:
p->icmpv4vars.id=icmp4eh->id;
p->icmpv4vars.seq=icmp4eh->seq;
if (p->icmpv4h->code!=0) {
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
}
break;
case ICMP_ADDRESS:
p->icmpv4vars.id=icmp4eh->id;
p->icmpv4vars.seq=icmp4eh->seq;
if (p->icmpv4h->code!=0) {
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
}
break;
case ICMP_ADDRESSREPLY:
p->icmpv4vars.id=icmp4eh->id;
p->icmpv4vars.seq=icmp4eh->seq;
if (p->icmpv4h->code!=0) {
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
}
break;
default:
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_TYPE);
}
return;
}
@ -84,7 +216,7 @@ void DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
/** DecodeICMPV4test01
* \brief
* \retval 0 Expected test value
* \retval 1 Expected test value
*/
static int DecodeICMPV4test01(void) {
uint8_t raw_icmpv4[] = {
@ -104,12 +236,19 @@ static int DecodeICMPV4test01(void) {
memset(&dtv, 0, sizeof(DecodeThreadVars));
DecodeICMPV4(&tv, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
if (NULL!=p.icmpv4h) {
if (p.icmpv4h->type==8 && p.icmpv4h->code==0) {
return 1;
}
}
return 0;
}
/** DecodeICMPV4test02
* \brief
* \retval 0 Expected test value
* \retval 1 Expected test value
*/
static int DecodeICMPV4test02(void) {
uint8_t raw_icmpv4[] = {
@ -129,12 +268,20 @@ static int DecodeICMPV4test02(void) {
memset(&dtv, 0, sizeof(DecodeThreadVars));
DecodeICMPV4(&tv, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
if (NULL!=p.icmpv4h) {
if (p.icmpv4h->type==0 && p.icmpv4h->code==0) {
return 1;
}
}
return 0;
}
/** DecodeICMPV4test03
* \brief TTL exceeded
* \retval Expected test value: 0
* \retval Expected test value: 1
*/
static int DecodeICMPV4test03(void) {
uint8_t raw_icmpv4[] = {
@ -152,12 +299,19 @@ static int DecodeICMPV4test03(void) {
memset(&dtv, 0, sizeof(DecodeThreadVars));
DecodeICMPV4(&tv, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
if (NULL!=p.icmpv4h) {
if (p.icmpv4h->type==11 && p.icmpv4h->code==0) {
return 1;
}
}
return 0;
}
/** DecodeICMPV4test04
* \brief dest. unreachable, administratively prohibited
* \retval 0 Expected test value
* \retval 1 Expected test value
*/
static int DecodeICMPV4test04(void) {
uint8_t raw_icmpv4[] = {
@ -177,6 +331,13 @@ static int DecodeICMPV4test04(void) {
memset(&dtv, 0, sizeof(DecodeThreadVars));
DecodeICMPV4(&tv, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
if (NULL!=p.icmpv4h) {
if (p.icmpv4h->type==3 && p.icmpv4h->code==10) {
return 1;
}
}
return 0;
}
@ -214,19 +375,77 @@ static int ICMPV4CalculateInvalidChecksumtest06(void) {
return (csum == ICMPV4CalculateChecksum((uint16_t *)raw_icmpv4, sizeof(raw_icmpv4)));
}
static int ICMPV4InvalidType07(void) {
uint8_t raw_icmpv4[] = {
0xff, 0x00, 0xab, 0x9b, 0x7f, 0x2b, 0x05, 0x2c,
0x3f, 0x72, 0x93, 0x4a, 0x00, 0x4d, 0x0a, 0x00,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38};
Packet p;
ThreadVars tv;
DecodeThreadVars dtv;
memset(&tv, 0, sizeof(ThreadVars));
memset(&p, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
DecodeICMPV4(&tv, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
if(DECODER_ISSET_EVENT(&p,ICMPV4_UNKNOWN_TYPE)) {
return 1;
}
return 0;
}
/** DecodeICMPV4test08
* \brief
* \retval 1 Expected test value - what we really want is not to segfault
*/
static int DecodeICMPV4test08(void) {
uint8_t raw_icmpv4[] = {
0x08, 0x00, 0x78, 0x47, 0xfc, 0x55, 0x00, 0x00
};
Packet p;
ThreadVars tv;
DecodeThreadVars dtv;
memset(&tv, 0, sizeof(ThreadVars));
memset(&p, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
DecodeICMPV4(&tv, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
if (NULL!=p.icmpv4h) {
if (p.icmpv4h->type==8 && p.icmpv4h->code==0) {
return 1;
}
}
return 0;
}
/**
* \brief Registers ICMPV4 unit test
* \todo More ICMPv4 tests
*/
void DecodeICMPV4RegisterTests(void) {
UtRegisterTest("DecodeICMPV4ttest01", DecodeICMPV4test01, 0);
UtRegisterTest("DecodeICMPV4ttest02", DecodeICMPV4test02, 0);
UtRegisterTest("DecodeICMPV4ttest03", DecodeICMPV4test03, 0);
UtRegisterTest("DecodeICMPV4ttest04", DecodeICMPV4test04, 0);
UtRegisterTest("DecodeICMPV4ttest01", DecodeICMPV4test01, 1);
UtRegisterTest("DecodeICMPV4ttest02", DecodeICMPV4test02, 1);
UtRegisterTest("DecodeICMPV4ttest03", DecodeICMPV4test03, 1);
UtRegisterTest("DecodeICMPV4ttest04", DecodeICMPV4test04, 1);
UtRegisterTest("ICMPV4CalculateValidChecksumtest05",
ICMPV4CalculateValidChecksumtest05, 1);
UtRegisterTest("ICMPV4CalculateInvalidChecksumtest06",
ICMPV4CalculateInvalidChecksumtest06, 0);
UtRegisterTest("DecodeICMPV4InvalidType", ICMPV4InvalidType07, 1);
UtRegisterTest("DecodeICMPV4ttest08", DecodeICMPV4test08, 1);
}
#endif /* UNITTESTS */

@ -3,7 +3,8 @@
#ifndef __DECODE_ICMPV4_H__
#define __DECODE_ICMPV4_H__
#define ICMPV4_HEADER_LEN 4
#define ICMPV4_HEADER_LEN 8
#ifndef ICMP_ECHOREPLY
#define ICMP_ECHOREPLY 0 /* Echo Reply */
#endif
@ -93,6 +94,7 @@
#endif
#ifndef ICMP_PREC_VIOLATION
#define ICMP_PREC_VIOLATION 14 /* Precedence violation */
#endif
#ifndef ICMP_PREC_CUTOFF
#define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
@ -128,22 +130,39 @@
/** marco for icmpv4 code access */
#define ICMPV4_GET_CODE(p) (p)->icmpv4h->code
typedef struct ICMPV4Vars_
{
uint8_t id;
uint8_t seq;
} ICMPV4Vars;
/* ICMPv4 header structure */
typedef struct ICMPV4Hdr_
{
uint8_t type;
uint8_t code;
uint16_t checksum;
/* XXX incomplete */
} ICMPV4Hdr;
/* ICMPv4 header structure */
typedef struct ICMPV4ExtHdr_
{
uint8_t type;
uint8_t code;
uint16_t checksum;
uint16_t id;
uint16_t seq;
} ICMPV4ExtHdr;
#define ICMPV4_HEADER_PKT_OFFSET 8
typedef struct ICMPV4Cache_ {
/* checksum computed over the icmpv4 packet */
int32_t comp_csum;
} ICMPV4Cache;
inline uint16_t ICMPV4CalculateChecksum(uint16_t *, uint16_t);
void DecodeICMPV4RegisterTests(void);
#endif /* __DECODE_ICMPV4_H__ */

@ -21,7 +21,77 @@
*/
void DecodePPPOEDiscovery(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
{
// TODO
PerfCounterIncr(dtv->counter_pppoe, tv->pca);
if (len < PPPOE_DISCOVERY_HEADER_MIN_LEN) {
DECODER_SET_EVENT(p, PPPOE_PKT_TOO_SMALL);
return;
}
p->pppoedh = (PPPOEDiscoveryHdr *)pkt;
if (p->pppoedh == NULL)
return;
/* parse the PPPOE code */
switch (ntohs(p->pppoedh->pppoe_code))
{
case PPPOE_CODE_PADI:
break;
case PPPOE_CODE_PADO:
break;
case PPPOE_CODE_PADR:
break;
case PPPOE_CODE_PADS:
break;
case PPPOE_CODE_PADT:
break;
default:
#ifdef DEBUG
printf("Unknown PPPOE code: %" PRIx32 "\n",ntohs(p->pppoedh->pppoe_code));
#endif
DECODER_SET_EVENT(p,PPPOE_WRONG_CODE);
}
/* parse any tags we have in the packet */
uint16_t tag_type, tag_length;
PPPOEDiscoveryTag* pppoedt = (PPPOEDiscoveryTag*) (p->pppoedh + PPPOE_DISCOVERY_HEADER_MIN_LEN);
uint16_t pppoe_length = ntohs(p->pppoedh->pppoe_length);
uint16_t packet_length = len - PPPOE_DISCOVERY_HEADER_MIN_LEN ;
if (pppoe_length>packet_length) {
#ifdef DEBUG
printf("Malformed PPPOE tags\n");
#endif
DECODER_SET_EVENT(p,PPPOE_MALFORMED_TAGS);
}
while (pppoe_length>=4 && packet_length>=4)
{
tag_type = ntohs(pppoedt->pppoe_tag_type);
tag_length = ntohs(pppoedt->pppoe_tag_length);
#ifdef DEBUG
printf ("PPPoE Tag type %x, length %u\n", tag_type, tag_length);
#endif
if (pppoe_length >= 4+tag_length) {
pppoe_length -= (4 + tag_length);
} else {
pppoe_length = 0; // don't want an underflow
}
if (packet_length >= 4+tag_length) {
packet_length -= (4 + tag_length);
} else {
packet_length = 0; // don't want an underflow
}
pppoedt = pppoedt + (4 + tag_length);
}
}
/**
@ -45,6 +115,8 @@ void DecodePPPOESession(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_
p->pppoesh->pppoe_version, p->pppoesh->pppoe_type, p->pppoesh->pppoe_code, ntohs(p->pppoesh->session_id), ntohs(p->pppoesh->pppoe_length));
#endif
/* can't use DecodePPP() here because we only get a single 2-byte word to indicate protocol instead of the full PPP header */
if (ntohs(p->pppoesh->pppoe_length) > 0) {
/* decode contained PPP packet */
@ -211,14 +283,14 @@ static int DecodePPPOEtest03 (void) {
}
/** DecodePPPOEtest04
* \brief Valid exaple PADI PPPOE packet taken from RFC2516
* \retval 0 Expected test value
* \brief Valid example PPPOE packet taken from RFC2516 - but with wrong PPPOE code
* \retval 1 Expected test value
*/
static int DecodePPPOEtest04 (void) {
/* example PADI packet taken from RFC2516 */
/* example PADI packet taken from RFC2516, but with wrong code */
uint8_t raw_pppoe[] = {
0x11, 0x09, 0x00, 0x00, 0x00, 0x04, 0x01, 0x01,
0x11, 0xbb, 0x00, 0x00, 0x00, 0x04, 0x01, 0x01,
0x00, 0x00
};
@ -228,9 +300,42 @@ static int DecodePPPOEtest04 (void) {
DecodePPPOEDiscovery(&tv, &dtv, &p, raw_pppoe, sizeof(raw_pppoe), NULL);
return 0; // TODO
if(DECODER_ISSET_EVENT(&p,PPPOE_WRONG_CODE)) {
return 1;
}
return 0;
}
/** DecodePPPOEtest05
* \brief Valid exaple PADO PPPOE packet taken from RFC2516, but too short for given length
* \retval 0 Expected test value
*/
static int DecodePPPOEtest05 (void) {
/* example PADI packet taken from RFC2516 */
uint8_t raw_pppoe[] = {
0x11, 0x07, 0x00, 0x00, 0x00, 0x20, 0x01, 0x01,
0x00, 0x00, 0x01, 0x02, 0x00, 0x18, 0x47, 0x6f,
0x20, 0x52, 0x65, 0x64, 0x42, 0x61, 0x63, 0x6b,
0x20, 0x2d, 0x20, 0x65, 0x73, 0x68, 0x73, 0x68
};
Packet p;
ThreadVars tv;
DecodeThreadVars dtv;
DecodePPPOEDiscovery(&tv, &dtv, &p, raw_pppoe, sizeof(raw_pppoe), NULL);
if(DECODER_ISSET_EVENT(&p,PPPOE_MALFORMED_TAGS)) {
return 1;
}
return 0;
}
/**
* \brief Registers PPPOE unit tests
* \todo More PPPOE tests
@ -239,6 +344,7 @@ void DecodePPPOERegisterTests(void) {
UtRegisterTest("DecodePPPOEtest01", DecodePPPOEtest01, 1);
UtRegisterTest("DecodePPPOEtest02", DecodePPPOEtest02, 0);
UtRegisterTest("DecodePPPOEtest03", DecodePPPOEtest03, 0);
UtRegisterTest("DecodePPPOEtest04", DecodePPPOEtest04, 0);
UtRegisterTest("DecodePPPOEtest04", DecodePPPOEtest04, 1);
UtRegisterTest("DecodePPPOEtest05", DecodePPPOEtest05, 1);
}

@ -18,6 +18,7 @@
#include "threadvars.h"
#define PPPOE_SESSION_HEADER_LEN 8
#define PPPOE_DISCOVERY_HEADER_MIN_LEN 6
typedef struct PPPOESessionHdr_
{
@ -33,7 +34,6 @@ typedef struct PPPOEDiscoveryTag_
{
uint16_t pppoe_tag_type;
uint16_t pppoe_tag_length;
uint8_t pppoe_tag_value[];
} PPPOEDiscoveryTag;
typedef struct PPPOEDiscoveryHdr_
@ -43,7 +43,6 @@ typedef struct PPPOEDiscoveryHdr_
uint8_t pppoe_code;
uint16_t discovery_id;
uint16_t pppoe_length;
PPPOEDiscoveryTag pppoe_tag_list[];
} PPPOEDiscoveryHdr;
/* see RFC 2516 - discovery codes */

@ -242,6 +242,7 @@ typedef struct Packet_
EthernetHdr *ethh;
PPPHdr *ppph;
PPPOESessionHdr *pppoesh;
PPPOEDiscoveryHdr *pppoedh;
GREHdr *greh;
IPV4Hdr *ip4h;
@ -255,6 +256,7 @@ typedef struct Packet_
ICMPV4Hdr *icmpv4h;
ICMPV4Cache icmpv4c;
ICMPV4Vars icmpv4vars;
ICMPV6Hdr *icmpv6h;
ICMPV6Cache icmpv6c;

Loading…
Cancel
Save