From 9adfe546206ea031b001dc201c18ad305d494f69 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 25 Aug 2009 20:14:01 +0100 Subject: [PATCH] more unit tests for pppoe - part I --- src/decode-ethernet.c | 57 +++++++++++- src/decode-ethernet.h | 4 +- src/decode-pppoe.c | 204 +++++++++++++++++++++++++++++++++--------- src/decode-pppoe.h | 41 +++++++-- src/decode.h | 5 +- src/eidps.c | 2 +- 6 files changed, 259 insertions(+), 54 deletions(-) diff --git a/src/decode-ethernet.c b/src/decode-ethernet.c index b163f3d467..80b9c2a60f 100644 --- a/src/decode-ethernet.c +++ b/src/decode-ethernet.c @@ -4,6 +4,8 @@ #include "decode-ethernet.h" #include "decode-events.h" +#include "util-unittest.h" + void DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { PerfCounterIncr(dtv->counter_eth, tv->pca); @@ -27,11 +29,60 @@ void DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *p } else if(ntohs(ethh->eth_type) == ETHERNET_TYPE_IPV6) { //printf("DecodeEthernet ip6\n"); DecodeIPV6(tv, dtv, p, pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, pq); - } else if(ntohs(ethh->eth_type) == ETHERNET_TYPE_PPPoE_SESS) { - //printf("DecodeEthernet PPPoE\n"); - DecodePPPoE(tv, dtv, p, pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, pq); + } else if(ntohs(ethh->eth_type) == ETHERNET_TYPE_PPPOE_SESS) { + //printf("DecodeEthernet PPPOE Session\n"); + DecodePPPOESession(tv, dtv, p, pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, pq); + } else if(ntohs(ethh->eth_type) == ETHERNET_TYPE_PPPOE_DISC) { + //printf("DecodeEthernet PPPOE Discovery\n"); + DecodePPPOEDiscovery(tv, dtv, p, pkt + ETHERNET_HEADER_LEN, len - ETHERNET_HEADER_LEN, pq); } return; } +/** DecodeEthernettest01 + * \brief Valid Ethernet packet + * \retval 0 Expected test value + */ +static int DecodeEthernetTest01 (void) { + + /* ICMP packet wrapped in PPPOE */ + uint8_t raw_eth[] = { + 0x00, 0x10, 0x94, 0x55, 0x00, 0x01, 0x00, 0x10, + 0x94, 0x56, 0x00, 0x01, 0x88, 0x64, 0x11, 0x00, + 0x00, 0x01, 0x00, 0x68, 0x00, 0x21, 0x45, 0xc0, + 0x00, 0x64, 0x00, 0x1e, 0x00, 0x00, 0xff, 0x01, + 0xa7, 0x78, 0x0a, 0x00, 0x00, 0x02, 0x0a, 0x00, + 0x00, 0x01, 0x08, 0x00, 0x4a, 0x61, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, + 0x3b, 0xd4, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd }; + + Packet p; + ThreadVars tv; + DecodeThreadVars dtv; + + memset(&dtv, 0, sizeof(DecodeThreadVars)); + memset(&tv, 0, sizeof(ThreadVars)); + memset(&p, 0, sizeof(Packet)); + + DecodeEthernet(&tv, &dtv, &p, raw_eth, sizeof(raw_eth), NULL); + + return 0; +} + + +/** + * \brief Registers Ethernet unit tests + * \todo More Ethernet tests + */ +void DecodeEthernetRegisterTests(void) { + UtRegisterTest("DecodeEthernetTest01", DecodeEthernetTest01, 0); +} diff --git a/src/decode-ethernet.h b/src/decode-ethernet.h index fa44707138..b2883331b2 100644 --- a/src/decode-ethernet.h +++ b/src/decode-ethernet.h @@ -12,8 +12,8 @@ #define ETHERNET_TYPE_EAPOL 0x888e #define ETHERNET_TYPE_IPV6 0x86dd #define ETHERNET_TYPE_IPX 0x8137 -#define ETHERNET_TYPE_PPPoE_DISC 0x8863 /* discovery stage */ -#define ETHERNET_TYPE_PPPoE_SESS 0x8864 /* session stage */ +#define ETHERNET_TYPE_PPPOE_DISC 0x8863 /* discovery stage */ +#define ETHERNET_TYPE_PPPOE_SESS 0x8864 /* session stage */ #define ETHERNET_TYPE_8021Q 0x8100 #define ETHERNET_TYPE_LOOP 0x9000 diff --git a/src/decode-pppoe.c b/src/decode-pppoe.c index 79be6ac5ad..ea912d9cdb 100644 --- a/src/decode-pppoe.c +++ b/src/decode-pppoe.c @@ -2,7 +2,7 @@ * \file Copyright (c) 2009 Open Information Security Foundation * \author James Riden * - * \brief PPPoE Decoder + * \brief PPPOE Decoder */ #include "eidps-common.h" @@ -17,41 +17,116 @@ #include "util-unittest.h" /** - * \brief Main decoding function for PPPoE packets + * \brief Main decoding function for PPPOE Discovery packets */ -void DecodePPPoE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) +void DecodePPPOEDiscovery(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) +{ + // TODO +} + +/** + * \brief Main decoding function for PPPOE Session packets + */ +void DecodePPPOESession(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) { PerfCounterIncr(dtv->counter_pppoe, tv->pca); - if (len < PPPOE_HEADER_LEN) { + if (len < PPPOE_SESSION_HEADER_LEN) { DECODER_SET_EVENT(p, PPPOE_PKT_TOO_SMALL); return; } - p->pppoeh = (PPPoEHdr *)pkt; - if (p->pppoeh == NULL) + p->pppoesh = (PPPOESessionHdr *)pkt; + if (p->pppoesh == NULL) return; #ifdef DEBUG printf("PPPOE VERSION %" PRIu32 " TYPE %" PRIu32 " CODE %" PRIu32 " SESSIONID %" PRIu32 " LENGTH %" PRIu32 "\n", - p->pppoeh->pppoe_version, p->pppoeh->pppoe_type, p->pppoeh->pppoe_code, ntohs(p->pppoeh->session_id), ntohs(p->pppoeh->pppoe_length)); + p->pppoesh->pppoe_version, p->pppoesh->pppoe_type, p->pppoesh->pppoe_code, ntohs(p->pppoesh->session_id), ntohs(p->pppoesh->pppoe_length)); #endif - if (ntohs(p->pppoeh->pppoe_length) > 0) { + if (ntohs(p->pppoesh->pppoe_length) > 0) { /* decode contained PPP packet */ - DecodePPP(tv, dtv, p, pkt + PPPOE_HEADER_LEN, len - PPPOE_HEADER_LEN, pq); + + switch (ntohs(p->pppoesh->protocol)) + { + case PPP_VJ_COMP: + case PPP_IPX: + case PPP_OSI: + case PPP_NS: + case PPP_DECNET: + case PPP_APPLE: + case PPP_BRPDU: + case PPP_STII: + case PPP_VINES: + case PPP_HELLO: + case PPP_LUXCOM: + case PPP_SNS: + case PPP_MPLS_UCAST: + case PPP_MPLS_MCAST: + case PPP_IPCP: + case PPP_OSICP: + case PPP_NSCP: + case PPP_DECNETCP: + case PPP_APPLECP: + case PPP_IPXCP: + case PPP_STIICP: + case PPP_VINESCP: + case PPP_IPV6CP: + case PPP_MPLSCP: + case PPP_LCP: + case PPP_PAP: + case PPP_LQM: + case PPP_CHAP: + DECODER_SET_EVENT(p,PPP_UNSUP_PROTO); + break; + + case PPP_VJ_UCOMP: + + if(len < (PPPOE_SESSION_HEADER_LEN + IPV4_HEADER_LEN)) { + DECODER_SET_EVENT(p,PPPVJU_PKT_TOO_SMALL); + return; + } + + if(IPV4_GET_RAW_VER((IPV4Hdr *)(pkt + PPPOE_SESSION_HEADER_LEN)) == 4) { + DecodeIPV4(tv, dtv, p, pkt + PPPOE_SESSION_HEADER_LEN, len - PPPOE_SESSION_HEADER_LEN, pq ); + } + break; + + case PPP_IP: + if(len < (PPPOE_SESSION_HEADER_LEN + IPV4_HEADER_LEN)) { + DECODER_SET_EVENT(p,PPPIPV4_PKT_TOO_SMALL); + return; + } + + DecodeIPV4(tv, dtv, p, pkt + PPPOE_SESSION_HEADER_LEN, len - PPPOE_SESSION_HEADER_LEN, pq ); + break; + + /* PPP IPv6 was not tested */ + case PPP_IPV6: + if(len < (PPPOE_SESSION_HEADER_LEN + IPV6_HEADER_LEN)) { + DECODER_SET_EVENT(p,PPPIPV6_PKT_TOO_SMALL); + return; + } + + DecodeIPV6(tv, dtv, p, pkt + PPPOE_SESSION_HEADER_LEN, len - PPPOE_SESSION_HEADER_LEN, pq ); + break; + + default: +#ifdef DEBUG + printf("Unknown PPP protocol: %" PRIx32 "\n",ntohs(p->ppph->protocol)); +#endif + DECODER_SET_EVENT(p,PPP_WRONG_TYPE); + return; + } } } -/** DecodePPPoEtest01 - * \brief Decode malformed PPPoE packet (too short) +/** DecodePPPOEtest01 + * \brief Decode malformed PPPOE packet (too short) * \retval 1 Expected test value */ -static int DecodePPPoEtest01 (void) { - - /* 0000 ff ff ff ff ff ff 00 0a e4 13 31 a3 81 00 03 98 ..........1..... - 0010 81 00 00 80 88 63 11 09 00 00 00 08 01 01 00 00 .....c.......... - 0020 01 00 00 00 */ +static int DecodePPPOEtest01 (void) { uint8_t raw_pppoe[] = { 0x11, 0x00, 0x00, 0x00, 0x00 }; Packet p; @@ -62,37 +137,36 @@ static int DecodePPPoEtest01 (void) { memset(&p, 0, sizeof(Packet)); memset(&dtv, 0, sizeof(DecodeThreadVars)); - DecodePPPoE(&tv, &dtv, &p, raw_pppoe, sizeof(raw_pppoe), NULL); + DecodePPPOESession(&tv, &dtv, &p, raw_pppoe, sizeof(raw_pppoe), NULL); - if(DECODER_ISSET_EVENT(&p,PPPOE_PKT_TOO_SMALL)) { + if (DECODER_ISSET_EVENT(&p,PPPOE_PKT_TOO_SMALL)) { return 1; } return 0; } -/** DecodePPPoEtest02 - * \brief Valid PPPoE packet +/** DecodePPPOEtest02 + * \brief Valid PPPOE packet * \retval 0 Expected test value */ -static int DecodePPPoEtest02 (void) { +static int DecodePPPOEtest02 (void) { uint8_t raw_pppoe[] = { 0x11, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x21, - 0x45, 0xc0, 0x00, 0x66, 0x02, 0xa3, 0x00, 0x00, - 0xff, 0xfd, 0x91, 0x7b, 0x64, 0x00, 0x00, 0x64, - 0xc0, 0x55, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x27, 0x56, 0x8b, 0xa4, 0x7c, 0xfa, - 0x38, 0x78, 0xb3, 0x70, 0x3f, 0xda, 0x79, 0x50, - 0x2e, 0xd7, 0x7f, 0x4d, 0x7c, 0xd2, 0xdc, 0x80, - 0xfa, 0x66 }; + 0x45, 0xc0, 0x00, 0x64, 0x00, 0x1e, 0x00, 0x00, + 0xff, 0x01, 0xa7, 0x78, 0x0a, 0x00, 0x00, 0x02, + 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x4a, 0x61, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x3b, 0xd4, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd }; Packet p; ThreadVars tv; @@ -102,7 +176,7 @@ static int DecodePPPoEtest02 (void) { memset(&p, 0, sizeof(Packet)); memset(&dtv, 0, sizeof(DecodeThreadVars)); - DecodePPPoE(&tv, &dtv, &p, raw_pppoe, sizeof(raw_pppoe), NULL); + DecodePPPOESession(&tv, &dtv, &p, raw_pppoe, sizeof(raw_pppoe), NULL); if(DECODER_ISSET_EVENT(&p,PPPOE_PKT_TOO_SMALL)) { return 1; @@ -111,12 +185,60 @@ static int DecodePPPoEtest02 (void) { return 0; } + +/** DecodePPPOEtest03 + * \brief Valid example PADO packet PPPOE packet taken from RFC2516 + * \retval 0 Expected test value + */ +static int DecodePPPOEtest03 (void) { + + /* example PADO 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, + 0x65, 0x73, 0x68, 0x6f, 0x6f, 0x74 + }; + + Packet p; + ThreadVars tv; + DecodeThreadVars dtv; + + DecodePPPOEDiscovery(&tv, &dtv, &p, raw_pppoe, sizeof(raw_pppoe), NULL); + + return 0; // TODO +} + +/** DecodePPPOEtest04 + * \brief Valid exaple PADI PPPOE packet taken from RFC2516 + * \retval 0 Expected test value + */ +static int DecodePPPOEtest04 (void) { + + /* example PADI packet taken from RFC2516 */ + uint8_t raw_pppoe[] = { + 0x11, 0x09, 0x00, 0x00, 0x00, 0x04, 0x01, 0x01, + 0x00, 0x00 + }; + + Packet p; + ThreadVars tv; + DecodeThreadVars dtv; + + DecodePPPOEDiscovery(&tv, &dtv, &p, raw_pppoe, sizeof(raw_pppoe), NULL); + + return 0; // TODO +} + /** - * \brief Registers PPPoE unit tests - * \todo More PPPoE tests + * \brief Registers PPPOE unit tests + * \todo More PPPOE tests */ -void DecodePPPoERegisterTests(void) { - UtRegisterTest("DecodePPPoEtest01", DecodePPPoEtest01, 1); - UtRegisterTest("DecodePPPoEtest02", DecodePPPoEtest02, 0); +void DecodePPPOERegisterTests(void) { + UtRegisterTest("DecodePPPOEtest01", DecodePPPOEtest01, 1); + UtRegisterTest("DecodePPPOEtest02", DecodePPPOEtest02, 0); + UtRegisterTest("DecodePPPOEtest03", DecodePPPOEtest03, 0); + UtRegisterTest("DecodePPPOEtest04", DecodePPPOEtest04, 0); } diff --git a/src/decode-pppoe.h b/src/decode-pppoe.h index 1b0f33d956..d27c5997dd 100644 --- a/src/decode-pppoe.h +++ b/src/decode-pppoe.h @@ -2,7 +2,7 @@ * \file Copyright (c) 2009 Open Infosec Foundation * \author James Riden * - * PPPoE Decoder header file + * PPPOE Decoder header file */ #ifndef __DECODE_PPPOE_H__ @@ -17,24 +17,55 @@ #include "decode.h" #include "threadvars.h" -#define PPPOE_HEADER_LEN 6 +#define PPPOE_SESSION_HEADER_LEN 8 -typedef struct _PPPoEHdr +typedef struct PPPOESessionHdr_ { unsigned pppoe_version : 4; unsigned pppoe_type : 4; uint8_t pppoe_code; uint16_t session_id; uint16_t pppoe_length; -} PPPoEHdr; + uint16_t protocol; +} PPPOESessionHdr; +typedef struct PPPOEDiscoveryTag_ +{ + uint16_t pppoe_tag_type; + uint16_t pppoe_tag_length; + uint8_t pppoe_tag_value[]; +} PPPOEDiscoveryTag; + +typedef struct PPPOEDiscoveryHdr_ +{ + unsigned pppoe_version : 4; + unsigned pppoe_type : 4; + uint8_t pppoe_code; + uint16_t discovery_id; + uint16_t pppoe_length; + PPPOEDiscoveryTag pppoe_tag_list[]; +} PPPOEDiscoveryHdr; + +/* see RFC 2516 - discovery codes */ #define PPPOE_CODE_PADI 0x09 #define PPPOE_CODE_PADO 0x07 #define PPPOE_CODE_PADR 0x19 #define PPPOE_CODE_PADS 0x65 #define PPPOE_CODE_PADT 0xa7 -void DecodePPPoERegisterTests(void); +/* see RFC 2516 Appendix A */ +#define PPPOE_TAG_END_OF_LIST 0x0000 /* End-Of-List */ +#define PPPOE_TAG_SERVICE_NAME 0x0101 /* Service-Name */ +#define PPPOE_TAG_AC_NAME 0x0102 /* AC-Name */ +#define PPPOE_TAG_HOST_UNIQ 0x0103 /* Host-Uniq */ +#define PPPOE_TAG_AC_COOKIE 0x0104 /* AC-Cookie */ +#define PPPOE_TAG_VENDOR_SPECIFIC 0x0105 /* Vendor-Specific */ +#define PPPOE_TAG_RELAY_SESSION_ID 0x0110 /* Relay-Session-Id */ +#define PPPOE_TAG_SERVICE_NAME_ERROR 0x0201 /* Service-Name-Error */ +#define PPPOE_TAG_AC_SYS_ERROR 0x0202 /* AC-System Error */ +#define PPPOE_TAG_GEN_ERROR 0x0203 /* Generic-Error */ + +void DecodePPPOERegisterTests(void); #endif /* __DECODE_PPPOE_H__ */ diff --git a/src/decode.h b/src/decode.h index 95bafe0e69..02e50c1253 100644 --- a/src/decode.h +++ b/src/decode.h @@ -241,7 +241,7 @@ typedef struct Packet_ /* header pointers */ EthernetHdr *ethh; PPPHdr *ppph; - PPPoEHdr *pppoeh; + PPPOESessionHdr *pppoesh; GREHdr *greh; IPV4Hdr *ip4h; @@ -402,7 +402,8 @@ typedef struct DecodeThreadVars_ void DecodeEthernet(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); void DecodeSll(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); void DecodePPP(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); -void DecodePPPoE(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); +void DecodePPPOESession(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); +void DecodePPPOEDiscovery(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); void DecodeTunnel(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); void DecodeIPV4(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); void DecodeIPV6(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *); diff --git a/src/eidps.c b/src/eidps.c index aec7937fde..74944d56c9 100644 --- a/src/eidps.c +++ b/src/eidps.c @@ -972,7 +972,7 @@ int main(int argc, char **argv) PerfRegisterTests(); DecodePPPRegisterTests(); HTTPParserRegisterTests(); - DecodePPPoERegisterTests(); + DecodePPPOERegisterTests(); DecodeICMPV4RegisterTests(); DecodeIPV4RegisterTests(); DecodeTCPRegisterTests();