looking inside ICMP packets

remotes/origin/master-1.0.x
Jamie 16 years ago committed by Victor Julien
parent ec6c5258b6
commit 0dc471db9c

@ -23,6 +23,8 @@ enum {
ICMPV4_PKT_TOO_SMALL,
ICMPV4_UNKNOWN_TYPE,
ICMPV4_UNKNOWN_CODE,
ICMPV4_IPV4_TRUNC_PKT,
ICMPV4_IPV4_UNKNOWN_VER,
/* ICMPv6 EVENTS */
ICMPV6_UNKNOWN_TYPE,

@ -60,11 +60,97 @@ inline uint16_t ICMPV4CalculateChecksum(uint16_t *pkt, uint16_t tlen)
}
/**
* \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 )
void DecodePartialIPV4( Packet* p, uint8_t* partial_packet, uint16_t len )
{
/** Check the sizes, the header must fit at least */
if (len < IPV4_HEADER_LEN) {
SCLogDebug("DecodePartialIPV4: ICMPV4_IPV4_TRUNC_PKT");
DECODER_SET_EVENT(p, ICMPV4_IPV4_TRUNC_PKT);
return;
}
IPV4Hdr *icmp4_ip4h = (IPV4Hdr*)partial_packet;
uint8_t* foo=(uint8_t*)icmp4_ip4h;
/** Check the embedded version */
if (IPV4_GET_RAW_VER(icmp4_ip4h)!=4) {
/** Check the embedded version */
SCLogDebug("DecodePartialIPV4: ICMPv4 contains Unknown IPV4 version "
"ICMPV4_IPV4_UNKNOWN_VER");
DECODER_SET_EVENT(p, ICMPV4_IPV4_UNKNOWN_VER);
return;
}
/** We need to fill icmpv4vars */
p->icmpv4vars.emb_ipv4h = icmp4_ip4h;
/** Get the IP address from the contained packet */
p->icmpv4vars.emb_ip4_src = IPV4_GET_RAW_IPSRC(icmp4_ip4h);
p->icmpv4vars.emb_ip4_dst = IPV4_GET_RAW_IPDST(icmp4_ip4h);
p->icmpv4vars.emb_ip4_hlen=IPV4_GET_RAW_HLEN(icmp4_ip4h) << 2;
switch (IPV4_GET_RAW_IPPROTO(icmp4_ip4h)) {
case IPPROTO_TCP:
if (len >= IPV4_HEADER_LEN + TCP_HEADER_LEN ) {
p->icmpv4vars.emb_tcph = (TCPHdr*)(partial_packet + IPV4_HEADER_LEN);
p->icmpv4vars.emb_sport = p->icmpv4vars.emb_tcph->th_sport;
p->icmpv4vars.emb_dport = p->icmpv4vars.emb_tcph->th_dport;
SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->TCP header sport: "
"%"PRIu8" dport %"PRIu8"", p->icmpv4vars.emb_sport,
p->icmpv4vars.emb_dport);
} else {
SCLogDebug("DecodePartialIPV4: Warning, ICMPV4->IPV4->TCP "
"header Didn't fit in the packet!");
p->icmpv4vars.emb_sport = 0;
p->icmpv4vars.emb_dport = 0;
}
break;
case IPPROTO_UDP:
if (len >= IPV4_HEADER_LEN + UDP_HEADER_LEN ) {
p->icmpv4vars.emb_udph = (UDPHdr*)(partial_packet + IPV4_HEADER_LEN);
p->icmpv4vars.emb_sport = p->icmpv4vars.emb_udph->uh_sport;
p->icmpv4vars.emb_dport = p->icmpv4vars.emb_udph->uh_dport;
SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->UDP header sport: "
"%"PRIu8" dport %"PRIu8"", p->icmpv4vars.emb_sport,
p->icmpv4vars.emb_dport);
} else {
SCLogDebug("DecodePartialIPV4: Warning, ICMPV4->IPV4->UDP "
"header Didn't fit in the packet!");
p->icmpv4vars.emb_sport = 0;
p->icmpv4vars.emb_dport = 0;
}
break;
case IPPROTO_ICMP:
p->icmpv4vars.emb_icmpv4h = (ICMPV4Hdr*)(partial_packet + IPV4_HEADER_LEN);
p->icmpv4vars.emb_sport = 0;
p->icmpv4vars.emb_dport = 0;
SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->ICMP header");
break;
}
/* debug print */
#ifdef DEBUG
char s[16], d[16];
inet_ntop(AF_INET, &(p->icmpv4vars.emb_ip4_src), s, sizeof(s));
inet_ntop(AF_INET, &(p->icmpv4vars.emb_ip4_dst), d, sizeof(d));
SCLogDebug("ICMPv4 embedding IPV4 %s->%s - CLASS: %" PRIu32 " FLOW: "
"%" PRIu32 " NH: %" PRIu32 " PLEN: %" PRIu32 " HLIM: %" PRIu32,
s, d, IPV4_GET_RAW_CLASS(icmp4_ip4h), IPV4_GET_RAW_FLOW(icmp4_ip4h),
IPV4_GET_RAW_NH(icmp4_ip4h), IPV4_GET_RAW_PLEN(icmp4_ip4h), IPV4_GET_RAW_HLIM(icmp4_ip4h));
#endif
return;
}
/** DecodeICMPV4
@ -98,12 +184,12 @@ void DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
break;
case ICMP_DEST_UNREACH:
if (p->icmpv4h->code>ICMP_SR_FAILED) {
if (p->icmpv4h->code>NR_ICMP_UNREACH) {
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 );
DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
}
break;
@ -113,7 +199,7 @@ void DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
} 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 );
DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
}
break;
@ -123,7 +209,7 @@ void DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
} 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 );
DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
}
break;
@ -141,7 +227,7 @@ void DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
} 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 );
DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
}
break;
@ -151,7 +237,7 @@ void DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
} 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 );
DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
}
break;
@ -299,13 +385,32 @@ static int DecodeICMPV4test03(void) {
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;
}
if (NULL==p.icmpv4h) {
return 0;
}
return 0;
// check it's type 11 code 0
if (p.icmpv4h->type!=11 || p.icmpv4h->code!=0) {
return 0;
}
// check it's source port 4747 to port 43650
if (p.icmpv4vars.emb_sport != 4747 || p.icmpv4vars.emb_dport != 43650) {
return 0;
}
// check the src,dst IPs contained inside
char s[16], d[16];
inet_ntop(AF_INET, &(p.icmpv4vars.emb_ip4_src), s, sizeof(s));
inet_ntop(AF_INET, &(p.icmpv4vars.emb_ip4_dst), d, sizeof(d));
// ICMPv4 embedding IPV4 192.168.1.13->209.85.227.147 pass
if (strcmp(s,"192.168.1.13")!=0 || strcmp(d,"209.85.227.147")!=0 ) {
return 0;
}
return 1;
}
/** DecodeICMPV4test04
@ -331,13 +436,32 @@ static int DecodeICMPV4test04(void) {
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;
}
if (NULL==p.icmpv4h) {
return 0;
}
return 0;
// check the type,code pair is correct - type 3, code 10
if (p.icmpv4h->type!=3 || p.icmpv4h->code!=10) {
return 0;
}
// check it's src port 2737 to dst port 12800
if (p.icmpv4vars.emb_sport != 2737 || p.icmpv4vars.emb_dport != 12800) {
return 0;
}
// check the src,dst IPs contained inside
char s[16], d[16];
inet_ntop(AF_INET, &(p.icmpv4vars.emb_ip4_src), s, sizeof(s));
inet_ntop(AF_INET, &(p.icmpv4vars.emb_ip4_dst), d, sizeof(d));
// ICMPv4 embedding IPV4 192.168.1.13->88.96.22.41
if (strcmp(s,"192.168.1.13")!=0 || strcmp(d,"88.96.22.41")!=0 ) {
return 0;
}
return 1;
}
static int ICMPV4CalculateValidChecksumtest05(void) {
@ -433,7 +557,6 @@ static int DecodeICMPV4test08(void) {
/**
* \brief Registers ICMPV4 unit test
* \todo More ICMPv4 tests
*/
void DecodeICMPV4RegisterTests(void) {
#ifdef UNITTESTS

@ -3,6 +3,10 @@
#ifndef __DECODE_ICMPV4_H__
#define __DECODE_ICMPV4_H__
#include "decode.h"
#include "decode-tcp.h"
#include "decode-udp.h"
#define ICMPV4_HEADER_LEN 8
#ifndef ICMP_ECHOREPLY
@ -130,12 +134,6 @@
/** 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_
{
@ -154,8 +152,69 @@ typedef struct ICMPV4ExtHdr_
uint16_t seq;
} ICMPV4ExtHdr;
/* ICMPv4 vars */
typedef struct ICMPV4Vars_
{
uint8_t type;
uint8_t code;
/* checksum of the icmpv4 packet */
uint16_t csum;
uint16_t id;
uint16_t seq;
uint32_t mtu;
uint32_t error_ptr;
/** Pointers to the embedded packet headers */
IPV4Hdr *emb_ipv4h;
TCPHdr *emb_tcph;
UDPHdr *emb_udph;
ICMPV4Hdr *emb_icmpv4h;
/** IPv4 src and dst address */
struct in_addr emb_ip4_src;
struct in_addr emb_ip4_dst;
uint8_t emb_ip4_hlen;
/** TCP/UDP ports */
uint16_t emb_sport;
uint16_t emb_dport;
} ICMPV4Vars;
#define ICMPV4_HEADER_PKT_OFFSET 8
/** macro for icmpv4 "type" access */
#define ICMPV4_GET_TYPE(p) (p)->icmpv4h->type
/** macro for icmpv4 "code" access */
#define ICMPV4_GET_CODE(p) (p)->icmpv4h->code
/** macro for icmpv4 "csum" access */
#define ICMPV4_GET_CSUM(p) (p)->icmpv4h->csum
/** If message is informational */
/** macro for icmpv4 "id" access */
#define ICMPV4_GET_ID(p) (p)->icmpv4h->icmpv4b.icmpv4i.id
/** macro for icmpv4 "seq" access */
#define ICMPV4_GET_SEQ(p) (p)->icmpv4h->icmpv4b.icmpv4i.seq
/** If message is Error */
/** macro for icmpv4 "unused" access */
#define ICMPV4_GET_UNUSED(p) (p)->icmpv4h->icmpv4b.icmpv4e.unused
/** macro for icmpv4 "error_ptr" access */
#define ICMPV4_GET_ERROR_PTR(p) (p)->icmpv4h->icmpv4b.icmpv4e.error_ptr
/** macro for icmpv4 "mtu" access */
#define ICMPV4_GET_MTU(p) (p)->icmpv4h->icmpv4b.icmpv4e.mtu
/** macro for icmpv4 embedded "protocol" access */
#define ICMPV4_GET_EMB_PROTO(p) (p)->icmpv4vars.emb_ip6_proto_next
/** macro for icmpv4 embedded "ipv4h" header access */
#define ICMPV4_GET_EMB_IPV4(p) (p)->icmpv4vars.emb_ipv4h
/** macro for icmpv4 embedded "tcph" header access */
#define ICMPV4_GET_EMB_TCP(p) (p)->icmpv4vars.emb_tcph
/** macro for icmpv4 embedded "udph" header access */
#define ICMPV4_GET_EMB_UDP(p) (p)->icmpv4vars.emb_udph
/** macro for icmpv4 embedded "icmpv4h" header access */
#define ICMPV4_GET_EMB_ICMPV4H(p) (p)->icmpv4vars.emb_icmpv4h
typedef struct ICMPV4Cache_ {
/* checksum computed over the icmpv4 packet */
int32_t comp_csum;

@ -67,6 +67,8 @@ typedef struct IPV4Hdr_
#define IPV4_GET_RAW_IPOFFSET(ip4h) ((ip4h)->ip_off)
#define IPV4_GET_RAW_IPTTL(ip4h) ((ip4h)->ip_ttl)
#define IPV4_GET_RAW_IPPROTO(ip4h) ((ip4h)->ip_proto)
#define IPV4_GET_RAW_IPSRC(ip4h) ((ip4h)->ip_src)
#define IPV4_GET_RAW_IPDST(ip4h) ((ip4h)->ip_dst)
/* we need to change them as well as get them */
#define IPV4_SET_RAW_VER(ip4h, value) ((ip4h)->ip_verhl = (((ip4h)->ip_verhl & 0x0f) | (value << 4)))

Loading…
Cancel
Save