extern const BaseApi* cd_gre;
extern const BaseApi* cd_gtp;
extern const BaseApi* cd_hopopts;
+extern const BaseApi* cd_ip4_embedded_in_icmp;
+extern const BaseApi* cd_ip6_embedded_in_icmp;
extern const BaseApi* cd_igmp;
extern const BaseApi* cd_mobility;
extern const BaseApi* cd_mpls;
#ifndef NO_NON_ETHER_DECODER
extern const BaseApi* cd_eapol;
extern const BaseApi* cd_linux_sll;
+extern const BaseApi* cd_ppp;
extern const BaseApi* cd_wlan;
#endif
cd_gre,
cd_gtp,
cd_hopopts,
+ cd_ip4_embedded_in_icmp,
+ cd_ip6_embedded_in_icmp,
cd_igmp,
cd_mobility,
cd_mpls,
#ifndef NO_NON_ETHER_DECODER
cd_eapol,
cd_linux_sll,
+ cd_ppp,
cd_wlan,
#endif
different valid next_header. The DECODE__UNSURE_ENCAP flag tells the next
decoder stage to silently ignore invalid headers. */
p->decode_flags |= DECODE__UNSURE_ENCAP;
+ p->decode_flags |= DECODE__TRUST_ON_FAIL;
const_cast<uint32_t&>(raw_len) -= (ESP_AUTH_DATA_LEN + ESP_TRAILER_LEN);
- p->decode_flags |= DECODE__ESP;
}
else
{
#include "config.h"
#endif
-#ifdef HAVE_DUMBNET_H
-#include <dumbnet.h>
-#else
-#include <dnet.h>
-#endif
-
#include "framework/codec.h"
#include "snort.h"
#include "protocols/icmp4.h"
virtual bool encode(EncState*, Buffer* out, const uint8_t* raw_in);
virtual bool update(Packet*, Layer*, uint32_t* len);
virtual void format(EncodeFlags, const Packet* p, Packet* c, Layer*);
-private:
- void DecodeICMPEmbeddedIP(const uint8_t *pkt, const uint32_t len, Packet *p);
+private:
void ICMP4AddrTests (Packet* );
void ICMP4MiscTests (Packet *);
* Returns: void function
*/
bool Icmp4Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len,
- Packet *p, uint16_t &lyr_len, uint16_t& /*next_prot_id*/)
+ Packet *p, uint16_t &lyr_len, uint16_t& next_prot_id)
{
- if(raw_len < icmp4::hdr_len())
+ if(raw_len < icmp::hdr_len())
{
DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
"WARNING: Truncated ICMP4 header (%d bytes).\n", raw_len););
switch (p->icmph->type)
{
// fall through ...
- case icmp4::IcmpType::SOURCE_QUENCH:
- case icmp4::IcmpType::DEST_UNREACH:
- case icmp4::IcmpType::REDIRECT:
- case icmp4::IcmpType::TIME_EXCEEDED:
- case icmp4::IcmpType::PARAMETERPROB:
- case icmp4::IcmpType::ECHOREPLY:
- case icmp4::IcmpType::ECHO:
- case icmp4::IcmpType::ROUTER_ADVERTISE:
- case icmp4::IcmpType::ROUTER_SOLICIT:
- case icmp4::IcmpType::INFO_REQUEST:
- case icmp4::IcmpType::INFO_REPLY:
+ case icmp::IcmpType::SOURCE_QUENCH:
+ case icmp::IcmpType::DEST_UNREACH:
+ case icmp::IcmpType::REDIRECT:
+ case icmp::IcmpType::TIME_EXCEEDED:
+ case icmp::IcmpType::PARAMETERPROB:
+ case icmp::IcmpType::ECHOREPLY:
+ case icmp::IcmpType::ECHO:
+ case icmp::IcmpType::ROUTER_ADVERTISE:
+ case icmp::IcmpType::ROUTER_SOLICIT:
+ case icmp::IcmpType::INFO_REQUEST:
+ case icmp::IcmpType::INFO_REPLY:
if (raw_len < 8)
{
DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
}
break;
- case icmp4::IcmpType::TIMESTAMP:
- case icmp4::IcmpType::TIMESTAMPREPLY:
+ case icmp::IcmpType::TIMESTAMP:
+ case icmp::IcmpType::TIMESTAMPREPLY:
if (raw_len < 20)
{
DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
}
break;
- case icmp4::IcmpType::ADDRESS:
- case icmp4::IcmpType::ADDRESSREPLY:
+ case icmp::IcmpType::ADDRESS:
+ case icmp::IcmpType::ADDRESSREPLY:
if (raw_len < 12)
{
DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
}
}
- lyr_len = icmp4::hdr_len();
+ lyr_len = icmp::hdr_len();
DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "ICMP type: %d code: %d\n",
p->icmph->type, p->icmph->code););
switch(p->icmph->type)
{
- case icmp4::IcmpType::ECHO:
+ case icmp::IcmpType::ECHO:
ICMP4AddrTests(p);
// fall through ...
- case icmp4::IcmpType::ECHOREPLY:
+ case icmp::IcmpType::ECHOREPLY:
/* setup the pkt id and seq numbers */
/* add the size of the echo ext to the data
* ptr and subtract it from the data size */
lyr_len += sizeof(ICMPHdr::icmp_hun.idseq);
break;
- case icmp4::IcmpType::DEST_UNREACH:
- if ((p->icmph->code == icmp4::IcmpCode::FRAG_NEEDED)
+ case icmp::IcmpType::DEST_UNREACH:
+ if ((p->icmph->code == icmp::IcmpCode::FRAG_NEEDED)
&& (ntohs(p->icmph->s_icmp_nextmtu) < 576))
{
codec_events::decoder_event(p, DECODE_ICMP_PATH_MTU_DOS);
/* Fall through */
- case icmp4::IcmpType::SOURCE_QUENCH:
- case icmp4::IcmpType::REDIRECT:
- case icmp4::IcmpType::TIME_EXCEEDED:
- case icmp4::IcmpType::PARAMETERPROB:
+ case icmp::IcmpType::SOURCE_QUENCH:
+ case icmp::IcmpType::REDIRECT:
+ case icmp::IcmpType::TIME_EXCEEDED:
+ case icmp::IcmpType::PARAMETERPROB:
/* account for extra 4 bytes in header */
lyr_len += 4;
- DecodeICMPEmbeddedIP(raw_pkt + lyr_len, raw_len - lyr_len, p);
+ next_prot_id = IP_EMBEDDED_IN_ICMP4;
break;
default:
return true;
}
-
+// TODO: delete
+#if 0
/*
* Function: DecodeICMPEmbeddedIP(uint8_t *, const uint32_t, Packet *)
*
uint16_t orig_frag_offset;
/* do a little validation */
- if(len < ipv4::hdr_len())
+ if(len < ip::hdr_len())
{
DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
"ICMP: IP short header (%d bytes)\n", len););
return;
}
-
+#endif
void Icmp4Codec::ICMP4AddrTests (Packet* p)
{
uint32_t dst = GET_DST_IP(p)->ip32[0];
// check all 32 bits; all set so byte order is irrelevant ...
- if ( ipv4::is_broadcast(dst) )
+ if ( ip::is_broadcast(dst) )
codec_events::decoder_event(p, DECODE_ICMP4_DST_BROADCAST);
/* - don't use htonl for speed reasons -
// check the 'msn' (most significant nibble) ...
msb_dst >>= 4;
- if( ipv4::is_multicast(msb_dst) )
+ if( ip::is_multicast(msb_dst) )
codec_events::decoder_event(p, DECODE_ICMP4_DST_MULTICAST);
}
void Icmp4Codec::ICMP4MiscTests (Packet *p)
{
if ((p->dsize == 0) &&
- (p->icmph->type == icmp4::IcmpType::ECHO))
+ (p->icmph->type == icmp::IcmpType::ECHO))
codec_events::decoder_event(p, DECODE_ICMP_PING_NMAP);
if ((p->dsize == 0) &&
(p->icmph->s_icmp_seq == 666))
codec_events::decoder_event(p, DECODE_ICMP_ICMPENUM);
- if ((p->icmph->type == icmp4::IcmpType::REDIRECT) &&
- (p->icmph->code == icmp4::IcmpCode::REDIR_HOST))
+ if ((p->icmph->type == icmp::IcmpType::REDIRECT) &&
+ (p->icmph->code == icmp::IcmpCode::REDIR_HOST))
codec_events::decoder_event(p, DECODE_ICMP_REDIRECT_HOST);
- if ((p->icmph->type == icmp4::IcmpType::REDIRECT) &&
- (p->icmph->code == icmp4::IcmpCode::REDIR_NET))
+ if ((p->icmph->type == icmp::IcmpType::REDIRECT) &&
+ (p->icmph->code == icmp::IcmpCode::REDIR_NET))
codec_events::decoder_event(p, DECODE_ICMP_REDIRECT_NET);
- if (p->icmph->type == icmp4::IcmpType::ECHOREPLY)
+ if (p->icmph->type == icmp::IcmpType::ECHOREPLY)
{
int i;
for (i = 0; i < p->ip_option_count; i++)
{
- if ( ipv4::is_opt_rr(p->ip_options[i].code) )
+ if (p->ip_options[i].is_opt_rr())
codec_events::decoder_event(p, DECODE_ICMP_TRACEROUTE_IPOPTS);
}
}
- if ((p->icmph->type == icmp4::IcmpType::SOURCE_QUENCH) &&
- (p->icmph->code == icmp4::IcmpCode::SOURCE_QUENCH_CODE))
+ if ((p->icmph->type == icmp::IcmpType::SOURCE_QUENCH) &&
+ (p->icmph->code == icmp::IcmpCode::SOURCE_QUENCH_CODE))
codec_events::decoder_event(p, DECODE_ICMP_SOURCE_QUENCH);
if ((p->dsize == 4) &&
- (p->icmph->type == icmp4::IcmpType::ECHO) &&
+ (p->icmph->type == icmp::IcmpType::ECHO) &&
(p->icmph->s_icmp_seq == 0) &&
- (p->icmph->code == icmp4::IcmpCode::ECHO_CODE))
+ (p->icmph->code == icmp::IcmpCode::ECHO_CODE))
codec_events::decoder_event(p, DECODE_ICMP_BROADSCAN_SMURF_SCANNER);
- if ((p->icmph->type == icmp4::IcmpType::DEST_UNREACH) &&
- (p->icmph->code == icmp4::IcmpCode::PKT_FILTERED))
+ if ((p->icmph->type == icmp::IcmpType::DEST_UNREACH) &&
+ (p->icmph->code == icmp::IcmpCode::PKT_FILTERED))
codec_events::decoder_event(p, DECODE_ICMP_DST_UNREACH_ADMIN_PROHIBITED);
- if ((p->icmph->type == icmp4::IcmpType::DEST_UNREACH) &&
- (p->icmph->code == icmp4::IcmpCode::PKT_FILTERED_HOST))
+ if ((p->icmph->type == icmp::IcmpType::DEST_UNREACH) &&
+ (p->icmph->code == icmp::IcmpCode::PKT_FILTERED_HOST))
codec_events::decoder_event(p, DECODE_ICMP_DST_UNREACH_DST_HOST_PROHIBITED);
- if ((p->icmph->type == icmp4::IcmpType::DEST_UNREACH) &&
- (p->icmph->code == icmp4::IcmpCode::PKT_FILTERED_NET))
+ if ((p->icmph->type == icmp::IcmpType::DEST_UNREACH) &&
+ (p->icmph->code == icmp::IcmpCode::PKT_FILTERED_NET))
codec_events::decoder_event(p, DECODE_ICMP_DST_UNREACH_DST_NET_PROHIBITED);
}
uint8_t* p;
IcmpHdr* ho;
- if (!update_buffer(out, sizeof(*ho) + enc->ip_len + icmp4::unreach_data()))
+ if (!update_buffer(out, sizeof(*ho) + enc->ip_len + icmp::unreach_data()))
return false;
const uint16_t *hi = reinterpret_cast<const uint16_t*>(raw_in);
ho = reinterpret_cast<IcmpHdr*>(out->base);
enc->proto = IPPROTO_ID_ICMPV4;
- ho->type = icmp4::IcmpType::DEST_UNREACH;
+ ho->type = icmp::IcmpType::DEST_UNREACH;
ho->code = get_icmp_code(enc->type);
ho->cksum = 0;
ho->unused = 0;
// copy first 8 octets of original ip data (ie udp header)
p += enc->ip_len;
- memcpy(p, hi, icmp4::unreach_data());
+ memcpy(p, hi, icmp::unreach_data());
ho->cksum = checksum::icmp_cksum((uint16_t *)ho, buff_diff(out, (uint8_t *)ho));
Packet *, uint16_t &lyr_len, uint16_t &next_prot_id);
virtual bool encode(EncState*, Buffer* out, const uint8_t* raw_in);
virtual bool update(Packet*, Layer*, uint32_t* len);
- virtual void format(EncodeFlags, const Packet* p, Packet* c, Layer*);
-
};
} // anonymous namespace
-static void DecodeICMPEmbeddedIP6(const uint8_t *pkt, const uint32_t len, Packet *p);
-
-
void Icmp6Codec::get_protocol_ids(std::vector<uint16_t>& v)
{
v.push_back(IPPROTO_ICMPV6);
//--------------------------------------------------------------------
bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len,
- Packet* p, uint16_t &lyr_len, uint16_t & /* next_prot_id */)
+ Packet* p, uint16_t &lyr_len, uint16_t & next_prot_id )
{
if(raw_len < icmp6::hdr_min_len())
{
return false;
}
- p->icmp6h = reinterpret_cast<icmp6::ICMP6Hdr*>(const_cast<uint8_t*>(raw_pkt));
+ const icmp6::ICMP6Hdr* icmp6h = reinterpret_cast<const icmp6::ICMP6Hdr*>(raw_pkt);
p->icmph = reinterpret_cast<const ICMPHdr*>(raw_pkt); /* This is needed for icmp rules */
if(IS_IP4(p))
{
- csum = checksum::cksum_add((uint16_t *)(p->icmp6h), raw_len);
+ csum = checksum::cksum_add((uint16_t *)(icmp6h), raw_len);
}
/* IPv6 traffic */
else
ph6.protocol = GET_IPH_PROTO(p);
ph6.len = htons((u_short)raw_len);
- csum = checksum::icmp_cksum((uint16_t *)(p->icmp6h), raw_len, &ph6);
+ csum = checksum::icmp_cksum((uint16_t *)(icmp6h), raw_len, &ph6);
}
if(csum)
{
p->data = raw_pkt + icmp6::hdr_min_len();
DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "ICMP type: %d code: %d\n",
- p->icmp6h->type, p->icmp6h->code););
+ icmp6h->type, icmp6h->code););
- switch(p->icmp6h->type)
+ switch(icmp6h->type)
{
case icmp6::Icmp6Types::ECHO:
case icmp6::Icmp6Types::REPLY:
codec_events::decoder_event(p, DECODE_ICMP_DGRAM_LT_ICMPHDR);
p->icmph = NULL;
- p->icmp6h = NULL;
return false;
}
break;
codec_events::decoder_event(p, DECODE_ICMPV6_TOO_BIG_BAD_MTU);
}
lyr_len = icmp6::hdr_normal_len();
- DecodeICMPEmbeddedIP6(p->data, p->dsize, p);
+ next_prot_id = IP_EMBEDDED_IN_ICMP6;
}
else
{
codec_events::decoder_event(p, DECODE_ICMP_DGRAM_LT_ICMPHDR);
p->icmph = NULL;
- p->icmp6h = NULL;
return false;
}
break;
p->data += 4;
p->dsize -= 4;
- if (p->icmp6h->type == icmp6::Icmp6Types::UNREACH)
+ if (icmp6h->type == icmp6::Icmp6Types::UNREACH)
{
- if (p->icmp6h->code == 2)
+ if (icmp6h->code == 2)
{
codec_events::decoder_event(p, DECODE_ICMPV6_UNREACHABLE_NON_RFC_2463_CODE);
}
- else if (p->icmp6h->code > 6)
+ else if (icmp6h->code > 6)
{
codec_events::decoder_event(p, DECODE_ICMPV6_UNREACHABLE_NON_RFC_4443_CODE);
}
}
lyr_len = icmp6::hdr_normal_len();
- DecodeICMPEmbeddedIP6(p->data, p->dsize, p);
+ next_prot_id = IP_EMBEDDED_IN_ICMP6;
}
else
{
codec_events::decoder_event(p, DECODE_ICMP_DGRAM_LT_ICMPHDR);
p->icmph = NULL;
- p->icmp6h = NULL;
return false;
}
break;
if (p->dsize >= (sizeof(ICMP6RouterAdvertisement) - icmp6::hdr_min_len()))
{
ICMP6RouterAdvertisement *ra = (ICMP6RouterAdvertisement *)raw_pkt;
- if (p->icmp6h->code != 0)
+ if (icmp6h->code != 0)
{
codec_events::decoder_event(p, DECODE_ICMPV6_ADVERT_BAD_CODE);
}
codec_events::decoder_event(p, DECODE_ICMP_DGRAM_LT_ICMPHDR);
p->icmph = NULL;
- p->icmp6h = NULL;
return false;
}
break;
codec_events::decoder_event(p, DECODE_ICMP_DGRAM_LT_ICMPHDR);
p->icmph = NULL;
- p->icmp6h = NULL;
return false;
}
break;
codec_events::decoder_event(p, DECODE_ICMP_DGRAM_LT_ICMPHDR);
p->icmph = NULL;
- p->icmp6h = NULL;
return false;
}
break;
default:
DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
- "WARNING: ICMP6_TYPE (type %d).\n", p->icmp6h->type););
+ "WARNING: ICMP6_TYPE (type %d).\n", icmp6h->type););
codec_events::decoder_event(p, DECODE_ICMP6_TYPE_OTHER);
lyr_len = icmp6::hdr_min_len();
}
+// TODO: delete (along with any mention of this function)
+
+#if 0
/*
* Function: DecodeICMPEmbeddedIP6(uint8_t *, const uint32_t, Packet *)
return;
}
+#endif
+
/******************************************************************
******************** E N C O D E R ******************************
// copy first 8 octets of original ip data (ie udp header)
// TBD: copy up to minimum MTU worth of data
- if (!update_buffer(out, icmp4::unreach_data()))
+ if (!update_buffer(out, icmp::unreach_data()))
return false;
- memcpy(out->base, raw_in, icmp4::unreach_data());
+ memcpy(out->base, raw_in, icmp::unreach_data());
// copy original ip header
return true;
}
-void Icmp6Codec::format (EncodeFlags, const Packet*, Packet* c, Layer* lyr)
-{
- // TBD handle nested icmp6 layers
- c->icmp6h = (ICMP6Hdr*)lyr->start;
-}
-
//-------------------------------------------------------------------------
// api
//-------------------------------------------------------------------------
for(i=0; i< (int) p->ip_option_count; i++) {
/* All IGMPv2 packets contain IP option code 148 (router alert).
This vulnerability only applies to IGMPv3, so return early. */
- if (ipv4::is_opt_rtralt(p->ip_options[i].code)) {
+ if (p->ip_options[i].is_opt_rtralt()) {
return true; /* No alert. */
}
uint16_t hlen; /* ip header length */
/* do a little validation */
- if(raw_len < ipv4::hdr_len())
+ if(raw_len < ip::IP4_HEADER_LEN)
{
DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
"WARNING: Truncated IP4 header (%d bytes).\n", raw_len););
}
/* lay the IP struct over the raw data */
- p->inner_iph = p->iph = reinterpret_cast<IPHdr*>(const_cast<uint8_t *>(raw_pkt));
+ IPHdr* iph = reinterpret_cast<IPHdr*>(const_cast<uint8_t *>(raw_pkt));
+ p->inner_iph = p->iph = iph;
/*
* with datalink DLT_RAW it's impossible to differ ARP datagrams from IP.
* So we are just ignoring non IP datagrams
*/
- if(ipv4::get_version((IPHdr*)raw_pkt) != 4)
+ if (iph->get_ver() != 4)
{
if ((p->decode_flags & DECODE__UNSURE_ENCAP) == 0)
codec_events::decoder_event(p, DECODE_NOT_IPV4_DGRAM);
/* get the IP datagram length */
ip_len = ntohs(p->iph->ip_len);
- hlen = ipv4::get_pkt_len(p->iph);
+ hlen = iph->get_hlen() << 2;
/* header length sanity check */
- if(hlen < ipv4::hdr_len())
+ if(hlen < ip::IP4_HEADER_LEN)
{
DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
"Bogus IP header length of %i bytes\n", hlen););
}
/* test for IP options */
- p->ip_options_len = (uint16_t)(hlen - ipv4::hdr_len());
+ p->ip_options_len = (uint16_t)(hlen - ip::IP4_HEADER_LEN);
if(p->ip_options_len > 0)
{
- p->ip_options_data = raw_pkt + ipv4::hdr_len();
- DecodeIPOptions((raw_pkt + ipv4::hdr_len()), p->ip_options_len, p);
+ p->ip_options_data = raw_pkt + ip::IP4_HEADER_LEN;
+ DecodeIPOptions((raw_pkt + ip::IP4_HEADER_LEN), p->ip_options_len, p);
}
else
{
}
// check all 32 bits ...
- if ( ipv4::is_broadcast(p->iph->ip_src.s_addr) )
+ if ( ip::is_broadcast(p->iph->ip_src.s_addr) )
codec_events::decoder_event(p, DECODE_IP4_SRC_BROADCAST);
- if ( ipv4::is_broadcast(p->iph->ip_dst.s_addr) )
+ if ( ip::is_broadcast(p->iph->ip_dst.s_addr) )
codec_events::decoder_event(p, DECODE_IP4_DST_BROADCAST);
/* Loopback traffic - don't use htonl for speed reasons -
msb_dst = (uint8_t)(p->iph->ip_dst.s_addr & 0xff);
#endif
// check the msb ...
- if ( ipv4::is_loopback(msb_src) || ipv4::is_loopback(msb_dst) )
+ if ( ip::is_loopback(msb_src) || ip::is_loopback(msb_dst) )
{
codec_events::decoder_event(p, DECODE_BAD_TRAFFIC_LOOPBACK);
}
// check the msb ...
- if ( ipv4::is_this_net(msb_src) )
+ if ( ip::is_this_net(msb_src) )
codec_events::decoder_event(p, DECODE_IP4_SRC_THIS_NET);
- if ( ipv4::is_this_net(msb_dst) )
+ if ( ip::is_this_net(msb_dst) )
codec_events::decoder_event(p, DECODE_IP4_DST_THIS_NET);
// check the 'msn' (most significant nibble) ...
msb_src >>= 4;
msb_dst >>= 4;
- if ( ipv4::is_multicast(msb_src) )
+ if ( ip::is_multicast(msb_src) )
codec_events::decoder_event(p, DECODE_IP4_SRC_MULTICAST);
- if ( ipv4::is_reserved(msb_src) )
+ if ( ip::is_reserved(msb_src) )
codec_events::decoder_event(p, DECODE_IP4_SRC_RESERVED);
- if ( ipv4::is_reserved(msb_dst))
+ if ( ip::is_reserved(msb_dst))
codec_events::decoder_event(p, DECODE_IP4_DST_RESERVED);
}
if (p->ip_options[i].data == NULL)
continue;
- if (ipv4::is_opt_rr(p->ip_options[i].code))
+ if (p->ip_options[i].is_opt_rr())
{
length = p->ip_options[i].len;
if (length < 1)
if (((length + 3) - pointer) % 4)
codec_events::decoder_event(p, DECODE_ICMP_DOS_ATTEMPT);
}
- else if (ipv4::is_opt_ts(p->ip_options[i].code))
+ else if (p->ip_options[i].is_opt_ts())
{
length = p->ip_options[i].len;
if (length < 2)
len_ptr = NULL;
}
- switch(static_cast<ipv4::IPOptionCodes>(*option_ptr))
+ switch(static_cast<ip::IPOptionCodes>(*option_ptr))
{
- case ipv4::IPOptionCodes::EOL:
+ case ip::IPOptionCodes::EOL:
done = 1;
// fall through
- case ipv4::IPOptionCodes::NOP:
+ case ip::IPOptionCodes::NOP:
/* if we hit an EOL, we're done */
p->ip_options[opt_count].len = 0;
/* IPv4 encoded header is hardcoded 20 bytes, we save some
* cycles and use the literal header size for checksum */
- ho->ip_csum = checksum::ip_cksum((uint16_t *)ho, ipv4::hdr_len());
+ ho->ip_csum = checksum::ip_cksum((uint16_t *)ho, ip::IP4_HEADER_LEN);
return true;
}
IPHdr* h = (IPHdr*)(lyr->start);
int i = lyr - p->layers;
- *len += ipv4::get_pkt_len(h);
+ *len += ip::get_pkt_len(h);
if ( i + 1 == p->num_layers )
{
if ( !PacketWasCooked(p) || (p->packet_flags & PKT_REBUILT_FRAG) )
{
h->ip_csum = 0;
- h->ip_csum = checksum::ip_cksum((uint16_t *)h, ipv4::get_pkt_len(h));
+ h->ip_csum = checksum::ip_cksum((uint16_t *)h, ip::get_pkt_len(h));
}
return true;
{
lyr->length = sizeof(*ch);
ch->ip_len = htons(lyr->length);
- ipv4::set_hlen(ch, lyr->length >> 2);
+ ip::set_hlen(ch, lyr->length >> 2);
}
}
sfiph_build(c, c->iph, AF_INET);
#include "packet_io/active.h"
#include "codecs/ip/cd_ipv6_module.h"
#include "codecs/sf_protocols.h"
+#include "protocols/protocol_ids.h"
namespace
{
void Ipv6Codec::get_protocol_ids(std::vector<uint16_t>& v)
{
- v.push_back(ipv6::ethertype());
- v.push_back(ipv6::prot_id());
+ v.push_back(ETHERTYPE_IPV6);
+ v.push_back(IPPROTO_ID_IPV6);
}
}
/* lay TCP on top of the data cause there is enough of it! */
- p->tcph = reinterpret_cast<TCPHdr*>(const_cast<uint8_t*>(raw_pkt));
+ p->tcph = reinterpret_cast<tcp::TCPHdr*>(const_cast<uint8_t*>(raw_pkt));
/* multiply the payload offset value by 4 */
lyr_len = TCP_OFFSET(p->tcph) << 2;
bool TcpCodec::encode (EncState* enc, Buffer* out, const uint8_t* raw_in)
{
int ctl;
- const TCPHdr* hi = reinterpret_cast<const TCPHdr*>(raw_in);
+ const tcp::TCPHdr* hi = reinterpret_cast<const tcp::TCPHdr*>(raw_in);
bool attach_payload = (enc->type == EncodeType::ENC_TCP_FIN ||
enc->type == EncodeType::ENC_TCP_PUSH);
if (!update_buffer(out, tcp::get_tcp_hdr_len(hi)))
return false;
- TCPHdr* ho = reinterpret_cast<TCPHdr*>(out->base);
+ tcp::TCPHdr* ho = reinterpret_cast<tcp::TCPHdr*>(out->base);
ctl = (hi->th_flags & TH_SYN) ? 1 : 0;
if ( forward(enc) )
ho->th_sum = 0;
- if (ipv4::get_version((IPHdr *)enc->ip_hdr) == 4) {
+ if (ip::get_version((IPHdr *)enc->ip_hdr) == 4) {
checksum::Pseudoheader ps;
int len = buff_diff(out, (uint8_t*)ho);
bool TcpCodec::update(Packet* p, Layer* lyr, uint32_t* len)
{
- TCPHdr* h = (TCPHdr*)(lyr->start);
+ tcp::TCPHdr* h = reinterpret_cast<tcp::TCPHdr*>(lyr->start);
*len += tcp::get_tcp_hdr_len(h) + p->dsize;
void TcpCodec::format(EncodeFlags f, const Packet* p, Packet* c, Layer* lyr)
{
- TCPHdr* ch = (TCPHdr*)lyr->start;
+ tcp::TCPHdr* ch = (tcp::TCPHdr*)lyr->start;
c->tcph = ch;
if ( reverse(f) )
{
int i = lyr - c->layers;
- TCPHdr* ph = (TCPHdr*)p->layers[i].start;
+ tcp::TCPHdr* ph = (tcp::TCPHdr*)p->layers[i].start;
ch->th_sport = ph->th_dport;
ch->th_dport = ph->th_sport;
#include "protocols/teredo.h"
#include "protocols/protocol_ids.h"
#include "protocols/icmp4.h"
-#include "protocols/icmp6.h"
#include "protocols/ipv4.h"
#include "protocols/protocol_ids.h"
#include "codecs/checksum.h"
ho->uh_len = htons((uint16_t)len);
ho->uh_chk = 0;
- if (ipv4::is_ipv4((ipv4::IPHdr*)enc->ip_hdr)) {
+ if (ip::is_ipv4(*(enc->ip_hdr))) {
checksum::Pseudoheader ps;
ps.sip = ((IPHdr *)enc->ip_hdr)->ip_src.s_addr;
ps.dip = ((IPHdr *)enc->ip_hdr)->ip_dst.s_addr;
}
// if this is not GTP, we want to return an ICMP unreachable packet
- else if ( ipv4::is_ipv4((ipv4::IPHdr*)enc->ip_hdr))
+ else if ( ip::is_ipv4(*(enc->ip_hdr)))
{
// copied directly from Icmp4Codec::encode()
uint8_t* p;
IcmpHdr* ho;
- if (!update_buffer(out, sizeof(*ho) + enc->ip_len + icmp4::unreach_data()))
+ if (!update_buffer(out, sizeof(*ho) + enc->ip_len + icmp::unreach_data()))
return false;
const uint16_t *hi = reinterpret_cast<const uint16_t*>(raw_in);
ho = reinterpret_cast<IcmpHdr*>(out->base);
enc->proto = IPPROTO_ID_ICMPV4;
- ho->type = icmp4::IcmpType::DEST_UNREACH;
+ ho->type = icmp::IcmpType::DEST_UNREACH;
ho->code = get_icmp_code(enc->type);
ho->cksum = 0;
ho->unused = 0;
// copy first 8 octets of original ip data (ie udp header)
p += enc->ip_len;
- memcpy(p, hi, icmp4::unreach_data());
+ memcpy(p, hi, icmp::unreach_data());
ho->cksum = checksum::icmp_cksum((uint16_t *)ho, buff_diff(out, (uint8_t *)ho));
}
// copy first 8 octets of original ip data (ie udp header)
// TBD: copy up to minimum MTU worth of data
- if (!update_buffer(out, icmp4::unreach_data()))
+ if (!update_buffer(out, icmp::unreach_data()))
return false;
- memcpy(out->base, raw_in, icmp4::unreach_data());
+ memcpy(out->base, raw_in, icmp::unreach_data());
// copy original ip header
if (!update_buffer(out, enc->ip_len))
case PPP_VJ_UCOMP:
/* VJ compression modifies the protocol field. It must be set
* to tcp (only TCP packets can be VJ compressed) */
- if(raw_len < (lyr_len + ipv4::hdr_len()))
+ if(raw_len < (lyr_len + ip::IP4_HEADER_LEN))
{
if (ScLogVerbose())
ErrorMessage("PPP VJ min packet length > captured len! "
if(STATIC_CODECS)
set(PLUGIN_LIST
+ cd_ip4_embedded_in_icmp.cc
+ cd_ip6_embedded_in_icmp.cc
+ cd_prot_embedded_in_icmp.cc
cd_gtp.cc
cd_gtp_module.h
cd_gtp_module.cc
add_shared_library(cd_gtp codecs cd_gtp.cc cd_gtp_module.h cd_gtp_module.cc)
add_shared_library(cd_teredo codecs cd_teredo.cc)
+ # When static codecs NOT enabled, the icmp files will be included in the
+ # ICMP libraries in the other file.
+
endif(STATIC_CODECS)
add_library( misc_codecs STATIC
ip_ver = *(raw_pkt + GTP_MIN_LEN) & 0xF0;
if (ip_ver == 0x40)
- next_prot_id = ipv4::prot_id();
+ next_prot_id = IPPROTO_ID_IPIP;
else if (ip_ver == 0x60)
- next_prot_id = ipv6::prot_id();
+ next_prot_id = IPPROTO_ID_IPV6;
}
return true;
--- /dev/null
+/*
+** Copyright (C) 2002-2013 Sourcefire, Inc.
+** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License Version 2 as
+** published by the Free Software Foundation. You may not use, modify or
+** distribute this program under any other version of the GNU General
+** Public License.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+// cd_ip4_embedded_in_icmp.cc author Josh Rosenbaum <jrosenba@cisco.com>
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "framework/codec.h"
+#include "protocols/ipv4.h"
+#include "codecs/decode_module.h"
+#include "codecs/codec_events.h"
+
+
+namespace
+{
+
+// yes, macros are necessary. The API and class constructor require different strings.
+//
+// this macros is defined in the module to ensure identical names. However,
+// if you don't want a module, define the name here.
+#ifndef IP4_EMBEDDED_IN_ICMP
+#define IP4_EMBEDDED_IN_ICMP "ip4_embedded_in_icmp"
+#endif
+
+class Ip4EmbeddedInIcmpCodec : public Codec
+{
+public:
+ Ip4EmbeddedInIcmpCodec() : Codec(IP4_EMBEDDED_IN_ICMP){};
+ ~Ip4EmbeddedInIcmpCodec() {};
+
+
+ virtual bool decode(const uint8_t *raw_pkt, const uint32_t &raw_len,
+ Packet *, uint16_t &lyr_len, uint16_t &next_prot_id);
+
+ virtual void get_protocol_ids(std::vector<uint16_t>&);
+
+};
+
+} // namespace
+
+// TODO: delete
+#include <iostream>
+
+void Ip4EmbeddedInIcmpCodec::get_protocol_ids(std::vector<uint16_t>& v)
+{
+ v.push_back(IP_EMBEDDED_IN_ICMP4);
+}
+
+bool Ip4EmbeddedInIcmpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
+ Packet* p, uint16_t& lyr_len, uint16_t& next_prot_id)
+{
+ uint32_t ip_len; /* length from the start of the ip hdr to the
+ * pkt end */
+ uint32_t hlen; /* ip header length */
+
+ /* do a little validation */
+ if(raw_len < ip::IP4_HEADER_LEN)
+ {
+ DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
+ "ICMP: IP short header (%d bytes)\n", raw_len););
+
+ codec_events::decoder_event(p, DECODE_ICMP_ORIG_IP_TRUNCATED);
+
+ return false;
+ }
+
+ /* lay the IP struct over the raw data */
+ const IPHdr *ip4h = reinterpret_cast<const IPHdr *>(raw_pkt);
+
+ /*
+ * with datalink DLT_RAW it's impossible to differ ARP datagrams from IP.
+ * So we are just ignoring non IP datagrams
+ */
+ if((ip4h->get_ver() != 4) && !IS_IP6(p))
+ {
+ DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
+ "ICMP: not IPv4 datagram ([ver: 0x%x][len: 0x%x])\n",
+ ip4h->get_ver(), ntohs(ip4h->get_len())););
+
+ codec_events::decoder_event(p, DECODE_ICMP_ORIG_IP_VER_MISMATCH);
+
+ return false;
+ }
+
+ ip_len = ntohs(ip4h->get_len());/* set the IP datagram length */
+ hlen = ip4h->get_len() << 2; /* set the IP header length */
+
+ if(raw_len < hlen)
+ {
+ DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
+ "ICMP: IP len (%d bytes) < IP hdr len (%d bytes), packet discarded\n",
+ ip_len, hlen););
+
+ codec_events::decoder_event(p, DECODE_ICMP_ORIG_DGRAM_LT_ORIG_IP);
+ return false;
+ }
+
+ /* set the remaining packet length */
+ ip_len = raw_len - hlen;
+
+ uint16_t orig_frag_offset = ntohs(ip4h->get_off());
+ orig_frag_offset &= 0x1FFF;
+
+ if (orig_frag_offset == 0)
+ {
+ /* Original IP payload should be 64 bits */
+ if (ip_len < 8)
+ {
+ codec_events::decoder_event(p, DECODE_ICMP_ORIG_PAYLOAD_LT_64);
+
+ return false;
+ }
+ /* ICMP error packets could contain as much of original payload
+ * as possible, but not exceed 576 bytes
+ */
+ else if (ntohs(GET_IPH_LEN(p)) > 576)
+ {
+ codec_events::decoder_event(p, DECODE_ICMP_ORIG_PAYLOAD_GT_576);
+ }
+ }
+ else
+ {
+ /* RFC states that only first frag will get an ICMP response */
+ codec_events::decoder_event(p, DECODE_ICMP_ORIG_IP_WITH_FRAGOFFSET);
+ return false;
+ }
+
+ DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "ICMP Unreachable IP header length: "
+ "%lu\n", (unsigned long)hlen););
+
+ // since we know the protocol ID in this layer (and NOT the
+ // next layer), set the correct protocol here. Normally,
+ // I would just set the next_protocol_id and let the packet_manger
+ // decode the next layer. However, I can't set the next_prot_id in
+ // this case because I don't want this going to the TCP, UDP, or
+ // ICMP codec. Therefore, doing a minor decode here.
+ switch(ip4h->get_proto())
+ {
+ case IPPROTO_TCP: /* decode the interesting part of the header */
+ p->proto_bits |= PROTO_BIT__TCP_EMBED_ICMP;
+ next_prot_id = PROT_EMBEDDED_IN_ICMP;
+ break;
+
+ case IPPROTO_UDP:
+ p->proto_bits |= PROTO_BIT__UDP_EMBED_ICMP;
+ next_prot_id = PROT_EMBEDDED_IN_ICMP;
+ break;
+
+ case IPPROTO_ICMP:
+ p->proto_bits |= PROTO_BIT__ICMP_EMBED_ICMP;
+ next_prot_id = PROT_EMBEDDED_IN_ICMP;
+ break;
+ }
+
+ return true;
+}
+
+//-------------------------------------------------------------------------
+// api
+//-------------------------------------------------------------------------
+
+
+static Codec* ctor(Module*)
+{
+ return new Ip4EmbeddedInIcmpCodec();
+}
+
+static void dtor(Codec *cd)
+{
+ delete cd;
+}
+
+
+static const CodecApi ip4_embedded_in_icmp_api =
+{
+ {
+ PT_CODEC,
+ IP4_EMBEDDED_IN_ICMP,
+ CDAPI_PLUGIN_V0,
+ 0,
+ nullptr, // module constructor
+ nullptr // module destructor
+ },
+ nullptr, // g_ctor
+ nullptr, // g_dtor
+ nullptr, // t_ctor
+ nullptr, // t_dtor
+ ctor,
+ dtor,
+};
+
+
+#ifdef BUILDING_SO
+SO_PUBLIC const BaseApi* snort_plugins[] =
+{
+ &name_api.base,
+ nullptr
+};
+#else
+const BaseApi* cd_ip4_embedded_in_icmp = &ip4_embedded_in_icmp_api.base;
+#endif
--- /dev/null
+/*
+** Copyright (C) 2002-2013 Sourcefire, Inc.
+** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License Version 2 as
+** published by the Free Software Foundation. You may not use, modify or
+** distribute this program under any other version of the GNU General
+** Public License.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+// cd_ip6_embedded_in_icmp.cc author Josh Rosenbaum <jrosenba@cisco.com>
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "framework/codec.h"
+#include "protocols/ipv4.h"
+#include "codecs/decode_module.h"
+#include "codecs/codec_events.h"
+
+
+namespace
+{
+
+// yes, macros are necessary. The API and class constructor require different strings.
+//
+// this macros is defined in the module to ensure identical names. However,
+// if you don't want a module, define the name here.
+#ifndef IP6_EMBEDDED_IN_ICMP
+#define IP6_EMBEDDED_IN_ICMP "ip6_embedded_in_icmp"
+#endif
+
+class Ip6EmbeddedInIcmpCodec : public Codec
+{
+public:
+ Ip6EmbeddedInIcmpCodec() : Codec(IP6_EMBEDDED_IN_ICMP){};
+ ~Ip6EmbeddedInIcmpCodec() {};
+
+
+ virtual void get_protocol_ids(std::vector<uint16_t>&);
+ virtual bool decode(const uint8_t *raw_pkt, const uint32_t &raw_len,
+ Packet *, uint16_t &lyr_len, uint16_t &next_prot_id);
+};
+
+} // namespace
+
+// TODO: delete
+#include <iostream>
+
+void Ip6EmbeddedInIcmpCodec::get_protocol_ids(std::vector<uint16_t>& v)
+{
+ v.push_back(IP_EMBEDDED_IN_ICMP6);
+}
+
+bool Ip6EmbeddedInIcmpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
+ Packet* p, uint16_t& lyr_len, uint16_t& next_prot_id)
+{
+// uint16_t orig_frag_offset;
+
+ /* lay the IP struct over the raw data */
+ const ipv6::IP6RawHdr* ip6h = reinterpret_cast<const ipv6::IP6RawHdr*>(raw_pkt);
+
+ DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "DecodeICMPEmbeddedIP6: ip header"
+ " starts at: %p, length is %lu\n", ip6h,
+ (unsigned long) raw_len););
+
+ /* do a little validation */
+ if ( raw_len < ipv6::hdr_len() )
+ {
+ DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
+ "ICMP6: IP short header (%d bytes)\n", raw_len););
+
+ codec_events::decoder_event(p, DECODE_ICMP_ORIG_IP_TRUNCATED);
+
+ return false;
+ }
+
+ /*
+ * with datalink DLT_RAW it's impossible to differ ARP datagrams from IP.
+ * So we are just ignoring non IP datagrams
+ */
+ if(ip6h->get_ver() != 6)
+ {
+ DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
+ "ICMP: not IPv6 datagram ([ver: 0x%x][len: 0x%x])\n",
+ ip6h->get_ver(), raw_len););
+
+ codec_events::decoder_event(p, DECODE_ICMP_ORIG_IP_VER_MISMATCH);
+
+ return false;
+ }
+
+ if ( raw_len < ipv6::hdr_len() )
+ {
+ DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
+ "ICMP6: IP6 len (%d bytes) < IP6 hdr len (%d bytes), packet discarded\n",
+ raw_len, ipv6::hdr_len()););
+
+ codec_events::decoder_event(p, DECODE_ICMP_ORIG_DGRAM_LT_ORIG_IP);
+
+ return false;
+ }
+
+// orig_frag_offset = ntohs(GET_ORIG_IPH_OFF(p));
+// orig_frag_offset &= 0x1FFF;
+
+ // XXX NOT YET IMPLEMENTED - fragments inside ICMP payload
+
+ DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "ICMP6 Unreachable IP6 header length: "
+ "%lu\n", (unsigned long)ipv6::hdr_len()););
+
+ // since we know the protocol ID in this layer (and NOT the
+ // next layer), set the correct protocol here. Normally,
+ // I would just set the next_protocol_id and let the packet_manger
+ // decode the next layer. However, I can't set the next_prot_id in
+ // this case because I don't want this going to the TCP, UDP, or
+ // ICMP codec. Therefore, doing a minor decode here.
+ switch(ip6h->get_next())
+ {
+ case IPPROTO_TCP: /* decode the interesting part of the header */
+ p->proto_bits |= PROTO_BIT__TCP_EMBED_ICMP;
+ next_prot_id = PROT_EMBEDDED_IN_ICMP;
+ break;
+
+ case IPPROTO_UDP:
+ p->proto_bits |= PROTO_BIT__UDP_EMBED_ICMP;
+ next_prot_id = PROT_EMBEDDED_IN_ICMP;
+ break;
+
+ case IPPROTO_ICMP:
+ p->proto_bits |= PROTO_BIT__ICMP_EMBED_ICMP;
+ next_prot_id = PROT_EMBEDDED_IN_ICMP;
+ break;
+ }
+
+ return true;
+}
+
+//-------------------------------------------------------------------------
+// api
+//-------------------------------------------------------------------------
+
+static Codec* ctor(Module*)
+{
+ return new Ip6EmbeddedInIcmpCodec();
+}
+
+static void dtor(Codec *cd)
+{
+ delete cd;
+}
+
+
+static const CodecApi ip6_embedded_in_icmp_api =
+{
+ {
+ PT_CODEC,
+ IP6_EMBEDDED_IN_ICMP,
+ CDAPI_PLUGIN_V0,
+ 0,
+ nullptr, // module constructor
+ nullptr // module destructor
+ },
+ nullptr, // g_ctor
+ nullptr, // g_dtor
+ nullptr, // t_ctor
+ nullptr, // t_dtor
+ ctor,
+ dtor,
+};
+
+
+#ifdef BUILDING_SO
+SO_PUBLIC const BaseApi* snort_plugins[] =
+{
+ &name_api.base,
+ nullptr
+};
+#else
+const BaseApi* cd_ip6_embedded_in_icmp = &ip6_embedded_in_icmp_api.base;
+#endif
--- /dev/null
+/*
+** Copyright (C) 2002-2013 Sourcefire, Inc.
+** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License Version 2 as
+** published by the Free Software Foundation. You may not use, modify or
+** distribute this program under any other version of the GNU General
+** Public License.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+// cd_prot_embedded_in_icmp.cc author Josh Rosenbaum <jrosenba@cisco.com>
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "framework/codec.h"
+
+
+namespace
+{
+
+// yes, macros are necessary. The API and class constructor require different strings.
+//
+// this macros is defined in the module to ensure identical names. However,
+// if you don't want a module, define the name here.
+#ifndef ProtEmbeddedInIcmp_NAME
+#define ProtEmbeddedInIcmp_NAME "prot_embedded_in_icmp"
+#endif
+
+class ProtEmbeddedInIcmp : public Codec
+{
+public:
+ ProtEmbeddedInIcmp() : Codec(ProtEmbeddedInIcmp_NAME){};
+ ~ProtEmbeddedInIcmp() {};
+
+
+ virtual bool decode(const uint8_t *raw_pkt, const uint32_t &raw_len,
+ Packet *, uint16_t &lyr_len, uint16_t &next_prot_id);
+
+ virtual void get_protocol_ids(std::vector<uint16_t>&);
+};
+
+} // namespace
+
+
+void ProtEmbeddedInIcmp::get_protocol_ids(std::vector<uint16_t>& v)
+{
+ v.push_back(PROT_EMBEDDED_IN_ICMP);
+}
+
+bool ProtEmbeddedInIcmp::decode(const uint8_t* /*raw_pkt*/, const uint32_t& /*raw_len*/,
+ Packet* /*p*/, uint16_t& /*lyr_len*/, uint16_t& /*next_prot_id*/)
+{
+
+ // Since the previous layer already set the correct p->proto_bits,
+ // there is really nothing to do here. This layer is actually
+ // a placeholder so I can easily find this layer's data at some
+ // other point in Snort++.
+ return true;
+}
+
+
+
+
+//-------------------------------------------------------------------------
+// api
+//-------------------------------------------------------------------------
+
+
+static Codec* ctor(Module*)
+{
+ return new ProtEmbeddedInIcmp();
+}
+
+static void dtor(Codec *cd)
+{
+ delete cd;
+}
+
+
+static const CodecApi prot_embedded_in_icmp_api =
+{
+ {
+ PT_CODEC,
+ ProtEmbeddedInIcmp_NAME,
+ CDAPI_PLUGIN_V0,
+ 0,
+ nullptr,
+ nullptr
+ },
+ nullptr, // ginit
+ nullptr, // gterm
+ nullptr, // tinit
+ nullptr, // tterm
+ ctor,
+ dtor,
+};
+
+
+#ifdef BUILDING_SO
+SO_PUBLIC const BaseApi* snort_plugins[] =
+{
+ &prot_embedded_in_icmp_api.base,
+ nullptr
+};
+#else
+const BaseApi* cd_prot_embedded_in_icmp = &prot_embedded_in_icmp_api.base;
+#endif
if (ENABLE_NON_ETHER_DECODERS)
set(NON_ETHER_PLUGINS
cd_linux_sll.cc
+ cd_ppp.cc
cd_wlan.cc
cd_wlan_module.h
cd_wlan_module.cc
# root_i4lrawip.cc
# root_oldpflog.cc
# root_enc.cc
- # root_ppp.cc
# root_pflog.cc
# root_pppserial.cc
# root_chdlc.cc
if (ENABLE_NON_ETHER_DECODERS)
add_shared_library(cd_wlan codecs cd_wlan.cc cd_wlan_module.h cd_wlan_module.cc)
add_shared_library(cd_linux_sll codecs cd_linux_sll.cc)
+ add_shared_library(cd_ppp codecs cd_ppp.cc)
endif(ENABLE_NON_ETHER_DECODERS)
endif(STATIC_CODECS)
if STATIC_CODECS
libroot_codecs_a_SOURCES += \
cd_linux_sll.cc \
+cd_ppp.cc \
cd_wlan.cc \
cd_wlan_module.h \
cd_wlan_module.cc
else
ehlibdir = $(pkglibdir)/codecs
-ehlib_LTLIBRARIES = libcd_wlan.la
-libcd_wlan_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
-libcd_wlan_la_LDFLAGS = -export-dynamic -shared
-libcd_wlan_la_SOURCES = cd_wlan.cc cd_wlan_module.h cd_wlan_module.cc
-
-ehlib_LTLIBRARIES += libcd_linux_sll.la
+ehlib_LTLIBRARIES = libcd_linux_sll.la
libcd_linux_sll_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
libcd_linux_sll_la_LDFLAGS = -export-dynamic -shared
libcd_linux_sll_la_SOURCES = cd_linux_sll.cc
+ehlib_LTLIBRARIES += libcd_ppp.la
+libcd_ppp_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
+libcd_ppp_la_LDFLAGS = -export-dynamic -shared
+libcd_ppp_la_SOURCES = cd_ppp.cc cd_ppp.h
+
+ehlib_LTLIBRARIES += libcd_wlan.la
+libcd_wlan_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
+libcd_wlan_la_LDFLAGS = -export-dynamic -shared
+libcd_wlan_la_SOURCES = cd_wlan.cc cd_wlan_module.h cd_wlan_module.cc
+
endif
endif
--- /dev/null
+/* $Id: decode.c,v 1.285 2013-06-29 03:03:00 rcombs Exp $ */
+
+/*
+** Copyright (C) 2002-2013 Sourcefire, Inc.
+** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License Version 2 as
+** published by the Free Software Foundation. You may not use, modify or
+** distribute this program under any other version of the GNU General
+** Public License.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <cstdint>
+#include "framework/codec.h"
+#include "main/snort.h"
+
+
+
+namespace
+{
+
+// yes, macros are necessary. The API and class constructor require different strings.
+//
+// this macros is defined in the module to ensure identical names. However,
+// if you don't want a module, define the name here.
+#ifndef PPP_NAME
+#define PPP_NAME "point_to_point"
+#endif
+
+class PPPCodec : public Codec
+{
+public:
+ PPPCodec() : Codec(PPP_NAME){}
+ ~PPPCodec() {}
+
+
+ virtual bool decode(const uint8_t *raw_pkt, const uint32_t &raw_len,
+ Packet *, uint16_t &lyr_len, uint16_t &next_prot_id);
+ virtual void get_data_link_type(std::vector<int>&);
+};
+
+} // namespace
+
+
+#ifndef DLT_PPP
+static constexpr int DLT_PPP = 51;
+#endif
+
+static constexpr uint8_t CHDLC_ADDR_BROADCAST = 0xff;
+static constexpr uint8_t CHDLC_CTRL_UNNUMBERED = 0x03;
+
+
+void PPPCodec::get_data_link_type(std::vector<int>& v)
+{
+ v.push_back(DLT_PPP);
+}
+
+
+bool PPPCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len,
+ Packet* /*p*/, uint16_t& lyr_len, uint16_t& next_prot_id)
+{
+ if(raw_len < 2)
+ {
+ if (ScLogVerbose())
+ {
+ ErrorMessage("Length not big enough for even a single "
+ "header or a one byte payload\n");
+ }
+ return false;
+ }
+
+ if(raw_pkt[0] == CHDLC_ADDR_BROADCAST && raw_pkt[1] == CHDLC_CTRL_UNNUMBERED)
+ {
+ /*
+ * Check for full HDLC header (rfc1662 section 3.2)
+ */
+ lyr_len = 2;
+ }
+
+ next_prot_id = ETHERTYPE_PPP;
+ return true;
+}
+
+
+
+//-------------------------------------------------------------------------
+// api
+//-------------------------------------------------------------------------
+
+
+static Codec* ctor(Module*)
+{
+ return new PPPCodec();
+}
+
+static void dtor(Codec *cd)
+{
+ delete cd;
+}
+
+
+static const CodecApi ppp_api =
+{
+ {
+ PT_CODEC,
+ PPP_NAME,
+ CDAPI_PLUGIN_V0,
+ 0,
+ nullptr, // mod_ctor
+ nullptr, // mod_dtor
+ },
+ nullptr, // pinit
+ nullptr, // pterm
+ nullptr, // tinit
+ nullptr, // tterm
+ ctor,
+ dtor,
+};
+
+
+#ifdef BUILDING_SO
+SO_PUBLIC const BaseApi* snort_plugins[] =
+{
+ &ppp_api.base,
+ nullptr
+};
+#else
+const BaseApi* cd_ppp = &ppp_api.base;
+#endif
+
+++ /dev/null
-/* $Id: decode.c,v 1.285 2013-06-29 03:03:00 rcombs Exp $ */
-
-/*
-** Copyright (C) 2002-2013 Sourcefire, Inc.
-** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License Version 2 as
-** published by the Free Software Foundation. You may not use, modify or
-** distribute this program under any other version of the GNU General
-** Public License.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-
-#include "framework/codec.h"
-
-
-static int DLT_PPP = 51;
-
-
-/*
- * Function: DecodePppPkt(Packet *, char *, DAQ_PktHdr_t*, uint8_t*)
- *
- * Purpose: Decode PPP traffic (either RFC1661 or RFC1662 framing).
- * This really is intended to handle IPCP
- *
- * Arguments: p => pointer to decoded packet struct
- * user => Utility pointer, unused
- * pkthdr => ptr to the packet header
- * pkt => pointer to the real live packet data
- *
- * Returns: void function
- */
-// DecodePppPkt() and DecodePppSerialPkt() may be incorrect ...
-// both skip past 2 byte protocol and then call DecodePppPktEncapsulated()
-// which does the same thing. That one works inside DecodePPPoEPkt();
-void DecodePppPkt(Packet * p, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt)
-{
- uint32_t cap_len = pkthdr->caplen;
- int hlen = 0;
-
- if(cap_len < 2)
- {
- if (ScLogVerbose())
- {
- ErrorMessage("Length not big enough for even a single "
- "header or a one byte payload\n");
- }
- MODULE_PROFILE_END(decodePerfStats);
- return;
- }
-
- if(pkt[0] == CHDLC_ADDR_BROADCAST && pkt[1] == CHDLC_CTRL_UNNUMBERED)
- {
- /*
- * Check for full HDLC header (rfc1662 section 3.2)
- */
- hlen = 2;
- }
-
- DecodePppPktEncapsulated(p->pkt + hlen, cap_len - hlen, p);
-
- MODULE_PROFILE_END(decodePerfStats);
- return;
-}
-
-
+++ /dev/null
-/*
-** Copyright (C) 2002-2013 Sourcefire, Inc.
-** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License Version 2 as
-** published by the Free Software Foundation. You may not use, modify or
-** distribute this program under any other version of the GNU General
-** Public License.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-
-
-#ifndef ROOT_PPP_H
-#define ROOT_PPP_H
-
-
-void DecodePppPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *);
-
-#endif /* ROOT_PPP_H */
-
return 0;
}
-
+ // FIXIT: Bug?? Do we want to check inner IP protocol tpe,
+ // when indexing outer ip array??
if (!snort_conf->ip_proto_array[GET_IPH_PROTO(p)])
{
switch (p->outer_family)
EventNode* en = (EventNode*)sfeventq_event_alloc(event_queue[qIndex]);
- if ( en )
+ if ( !en )
return -1;
en->otn = otn;
-
/*
** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
** Copyright (C) 2005-2013 Sourcefire, Inc.
port_h = srcPort;
}
if (ScMplsOverlappingIp() &&
- ipv4::isPrivateIP(*src) && ipv4::isPrivateIP(*dst))
+ ip::isPrivateIP(*src) && ip::isPrivateIP(*dst))
mplsLabel = mplsId;
else
mplsLabel = 0;
}
+
class Codec
{
public:
// Get the codec's name
inline const char* get_name(){return name; };
- // Several codecs are for convenience. So, tell Snort++ not to print any info
- virtual bool dump_at_startup(){ return true; };
// used for backwards compatability.
virtual PROTO_ID get_proto_id() { return PROTO_AH; };
// Registers this Codec's data link type (as defined by libpcap)
return (((uint8_t*)(buf->base+buf->end))-(uint8_t*)ho);
}
- static inline icmp4::IcmpCode get_icmp_code (EncodeType et)
+ static inline icmp::IcmpCode get_icmp_code (EncodeType et)
{
switch ( et ) {
- case EncodeType::ENC_UNR_NET: return icmp4::IcmpCode::NET_UNREACH;
- case EncodeType::ENC_UNR_HOST: return icmp4::IcmpCode::HOST_UNREACH;
- case EncodeType::ENC_UNR_PORT: return icmp4::IcmpCode::PORT_UNREACH;
- case EncodeType::ENC_UNR_FW: return icmp4::IcmpCode::PKT_FILTERED;
- default: return icmp4::IcmpCode::PORT_UNREACH;
+ case EncodeType::ENC_UNR_NET: return icmp::IcmpCode::NET_UNREACH;
+ case EncodeType::ENC_UNR_HOST: return icmp::IcmpCode::HOST_UNREACH;
+ case EncodeType::ENC_UNR_PORT: return icmp::IcmpCode::PORT_UNREACH;
+ case EncodeType::ENC_UNR_FW: return icmp::IcmpCode::PKT_FILTERED;
+ default: return icmp::IcmpCode::PORT_UNREACH;
}
}
{
Packet op;
Packet *orig_p;
- uint32_t orig_ip_hlen;
if (log == NULL || p == NULL)
return;
memset((char*)&op, 0, sizeof(op));
orig_p = &op;
- orig_p->iph = p->orig_iph;
- orig_p->tcph = p->orig_tcph;
- orig_p->udph = p->orig_udph;
- orig_p->sp = p->orig_sp;
- orig_p->dp = p->orig_dp;
- orig_p->icmph = p->orig_icmph;
- orig_p->iph_api = p->orig_iph_api;
-// orig_p->ip4h = p->orig_ip4h;
-// orig_p->ip6h = p->orig_ip6h;
- orig_p->family = p->orig_family;
-
- if(orig_p->iph != NULL)
+ if (!layer::set_api_ip_embed_icmp(p, op.ip_api))
{
- TextLog_Print(log, "\n** ORIGINAL DATAGRAM DUMP:\n");
- LogIPHeader(log, orig_p);
- orig_ip_hlen = ipv4::get_pkt_len(p->orig_iph) << 2;
-
- switch(GET_IPH_PROTO(orig_p))
+ switch(orig_p->ip_api.proto())
{
case IPPROTO_TCP:
- if(orig_p->tcph != NULL)
+ {
+ const tcp::TCPHdr* tcph = layer::get_tcp_embed_icmp(p);
+ if (tcph)
+ {
+ orig_p->sp = ntohs(tcph->th_sport);
+ orig_p->dp = ntohs(tcph->th_dport);
+ orig_p->tcph = tcph;
+ }
+
+ TextLog_Print(log, "\n** ORIGINAL DATAGRAM DUMP:\n");
+ LogIPHeader(log, orig_p);
+
+ if(tcph != NULL)
+ {
TextLog_Print(log, "Seq: 0x%lX\n",
(u_long)ntohl(orig_p->tcph->th_seq));
+ }
break;
+ }
case IPPROTO_UDP:
- if(orig_p->udph != NULL)
+ {
+ const udp::UDPHdr* udph = layer::get_udp_embed_icmp(p);
+ if (udph)
+ {
+ orig_p->sp = ntohs(p->udph->uh_sport);
+ orig_p->dp = ntohs(p->udph->uh_dport);
+ orig_p->udph = udph;
+ }
+
+ TextLog_Print(log, "\n** ORIGINAL DATAGRAM DUMP:\n");
+ LogIPHeader(log, orig_p);
+
+ if(udph != NULL)
TextLog_Print(log, "Len: %d Csum: %d\n",
ntohs(orig_p->udph->uh_len) - UDP_HEADER_LEN,
ntohs(orig_p->udph->uh_chk));
break;
+ }
case IPPROTO_ICMP:
- if(orig_p->icmph != NULL)
- LogEmbeddedICMPHeader(log, orig_p->icmph);
+ {
+ TextLog_Print(log, "\n** ORIGINAL DATAGRAM DUMP:\n");
+ LogIPHeader(log, orig_p);
+
+ const icmp::ICMPHdr* icmph = layer::get_icmp_embed_icmp(p);
+ if(icmph != NULL)
+ LogEmbeddedICMPHeader(log, icmph);
break;
+ }
default:
+ TextLog_Print(log, "\n** ORIGINAL DATAGRAM DUMP:\n");
+ LogIPHeader(log, orig_p);
+
TextLog_Print(log, "Protocol: 0x%X (unknown or "
"header truncated)", GET_IPH_PROTO(orig_p));
break;
} /* switch */
/* if more than 8 bytes of original IP payload sent */
+ uint32_t orig_ip_hlen = p->ip_api.hlen() << 2;
if (p->dsize - orig_ip_hlen > 8)
{
TextLog_Print(log, "(%d more bytes of original packet)\n",
set_ips_policy(sc->get_ips_policy());
set_network_policy(sc->get_network_policy());
+ sc->max_encapsulations = -1;
+
return sc;
}
if ( cmd_line->remote_control )
config_file->remote_control = cmd_line->remote_control;
+ if ( cmd_line->max_encapsulations )
+ config_file->max_encapsulations = cmd_line->max_encapsulations;
+
// config file vars are stored differently
// FIXIT should config_file and cmd_line use the same var list / table?
config_file->var_list = NULL;
enc->p = p;
enc->ip_hdr = p->layers[layer::get_inner_ip_lyr(p)].start;
- if ( ipv4::is_ipv4(*(enc->ip_hdr)))
- enc->ip_len = ipv4::get_pkt_len((IPHdr*) enc->ip_hdr);
+ if ( ip::is_ipv4(*(enc->ip_hdr)))
+ enc->ip_len = ip::get_pkt_len((IPHdr*) enc->ip_hdr);
else if ( ipv6::is_ip6_hdr_ver((ipv6::IP6RawHdr*)(enc->ip_hdr)))
enc->ip_len = sizeof(ipv6::IP6RawHdr);
else
std::find(s_codecs.begin(), s_codecs.end(), cd_api);
if (p == s_codecs.end())
- FatalError("PacketManager:: should never reach this code!!" \
+ FatalError("PacketManager:: should never reach this code!!"
"Cannot find Codec %s's api", cd_api->base.name);
int pos = p - s_codecs.begin();
// initialize all of the relevent data to decode this packet
memset(p, 0, PKT_ZERO_LEN);
+ p->ip_api.reset();
+
p->pkth = pkthdr;
p->pkt = pkt;
len = pkthdr->caplen;
// loop until the protocol id is no longer valid
while(s_protocols[mapped_prot]->decode(pkt, len, p, lyr_len, prot_id))
{
+ DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Codec %s (protocol_id: %u:"
+ "ip header starts at: %p, length is %lu\n",
+ s_protocols[mapped_prot]->get_name(), prot_id, pkt,
+ (unsigned long) len););
+
// must be done here after decode and before push for case layer
// LAYER_MAX+1 is invalid or the default codec
if ( p->num_layers == LAYER_MAX )
lyr_len = 0;
}
+ DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Codec %s (protocol_id: %hu: ip header"
+ " starts at: %p, length is %lu\n",
+ s_protocols[mapped_prot]->get_name(),
+ prot_id, pkt, (unsigned long) len););
+
+
// if the final protocol ID is not the default codec, a Codec failed
if (prev_prot_id != FINISHED_DECODE)
{
s_stats[other_codecs]++;
}
- if (p->decode_flags & DECODE__ESP)
+ if (p->decode_flags & DECODE__TRUST_ON_FAIL)
p->packet_flags |= PKT_TRUST;
}
{
encode_set_pkt(NULL);
}
-
};
#endif
-
unsigned i, sz = bindings.size();
Port port = (p->packet_flags & PKT_FROM_CLIENT) ? p->dp : p->sp;
- uint16_t vlan = vlan::vth_vlan(layer::get_vlan_layer(p));
+
+ if (p->proto_bits & PROTO_BIT__VLAN)
+ uint16_t vlan = vlan::vth_vlan(layer::get_vlan_layer(p));
for ( i = 0; i < sz; i++ )
{
/****************************************************************************
*
-** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
+ * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
* Copyright (C) 2005-2013 Sourcefire, Inc.
*
* This program is free software; you can redistribute it and/or modify
changes++;
}
}
- if ( p->layers[layer].length > IP_HEADER_LEN )
+ if ( p->layers[layer].length > ip::IP4_HEADER_LEN )
{
- uint8_t* opts = p->layers[layer].start + IP_HEADER_LEN;
- uint8_t len = p->layers[layer].length - IP_HEADER_LEN;
+ uint8_t* opts = p->layers[layer].start + ip::IP4_HEADER_LEN;
+ uint8_t len = p->layers[layer].length - ip::IP4_HEADER_LEN;
// expect len > 0 because IHL yields a multiple of 4
memset(opts, IPOPT_NOP, len);
normStats[PC_IP4_OPTS]++;
ICMPHdr* h = (ICMPHdr*)(p->layers[layer].start);
if ( (h->type == ICMP_ECHO || h->type == ICMP_ECHOREPLY) &&
- (h->code != icmp4::IcmpCode::ECHO_CODE) )
+ (h->code != icmp::IcmpCode::ECHO_CODE) )
{
- h->code = icmp4::IcmpCode::ECHO_CODE;
+ h->code = icmp::IcmpCode::ECHO_CODE;
normStats[PC_ICMP4_ECHO]++;
sfBase.iPegs[PERF_COUNT_ICMP4_ECHO]++;
changes++;
(uint16_t)h->type == icmp6::Icmp6Types::REPLY) &&
(h->code != 0) )
{
- h->code = static_cast<icmp4::IcmpCode>(0);
+ h->code = static_cast<icmp::IcmpCode>(0);
normStats[PC_ICMP6_ECHO]++;
sfBase.iPegs[PERF_COUNT_ICMP6_ECHO]++;
changes++;
static inline int Norm_TCPOptions (
NormalizerConfig* config,
- uint8_t* opts, size_t len, const TCPHdr* h, uint8_t numOpts, int changes)
+ uint8_t* opts, size_t len, const tcp::TCPHdr* h, uint8_t numOpts, int changes)
{
size_t i = 0;
uint8_t c = 0;
static int Norm_TCP (
NormalizerConfig* c, Packet * p, uint8_t layer, int changes)
{
- TCPHdr* h = (TCPHdr*)(p->layers[layer].start);
+ tcp::TCPHdr* h = (tcp::TCPHdr*)(p->layers[layer].start);
if ( h->th_offx2 & TH_RSV )
{
|| ((p->icmph != NULL) && (p->icmph->type == ICMP_DEST_UNREACH)
&& ((p->icmph->code == ICMP_PORT_UNREACH)
|| (p->icmph->code == ICMP_PKT_FILTERED))
- && (p->orig_tcph != NULL)))
+ && (p->proto_bits & PROTO_BIT__TCP_EMBED_ICMP)))
{
*proto = PS_PROTO_TCP;
return 0;
|| ((p->icmph != NULL) && (p->icmph->type == ICMP_DEST_UNREACH)
&& ((p->icmph->code == ICMP_PORT_UNREACH)
|| (p->icmph->code == ICMP_PKT_FILTERED))
- && (p->orig_udph != NULL)))
+ && (p->proto_bits & PROTO_BIT__UDP_EMBED_ICMP)))
{
*proto = PS_PROTO_UDP;
return 0;
eth.h
icmp4.h
icmp6.h
+ ip.cc
+ ip.h
ipv4.h
ipv6.h
gre.h
eth.h \
icmp4.h \
icmp6.h \
+ip.h \
+ip.cc \
ipv4.h \
ipv6.h \
gre.h \
#include "main/snort_types.h"
#include "protocols/ipv4.h"
-namespace icmp4
+namespace icmp
{
namespace detail
/* IP header for unreach */
struct ih_ip
{
- ipv4::IPHdr *ip;
+ ip::IPHdr *ip;
/* options and then 64 bits of data */
} ip;
return detail::ICMP_UNREACH_DATA;
}
-} //namespace icmp4
+} //namespace icmp
-typedef icmp4::ICMPbaseHdr ICMPbaseHdr;
-typedef icmp4::ICMPHdr ICMPHdr;
+typedef icmp::ICMPbaseHdr ICMPbaseHdr;
+typedef icmp::ICMPHdr ICMPHdr;
#ifndef ICMP_ECHOREPLY
const uint8_t ICMP_ECHOREPLY = 0; /* Echo Reply */
--- /dev/null
+/*
+** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
+** Copyright (C) 2007-2013 Sourcefire, Inc.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License Version 2 as
+** published by the Free Software Foundation. You may not use, modify or
+** distribute this program under any other version of the GNU General
+** Public License.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+// ip.cc author Josh Rosenbaum <jrosenba@cisco.com>
+
+#include "protocols/ip.h"
+#include "protocols/packet.h"
+
+namespace ip
+{
+
+void IpApi::reset()
+{
+ ip4h = nullptr;
+ ip6h = nullptr;
+ src_p = nullptr;
+ dst_p = nullptr;
+}
+
+void IpApi::set(const IPHdr* h4)
+{
+ ip4h = h4;
+ ip6h = nullptr;
+ src_p = nullptr;
+ dst_p = nullptr;
+}
+
+void IpApi::set(const ipv6::IP6RawHdr* h6)
+{
+ ip6h = h6;
+ ip4h = nullptr;
+ src_p = nullptr;
+ dst_p = nullptr;
+}
+
+bool IpApi::set(const uint8_t* raw_ip_data)
+{
+ const IPHdr* h4 = reinterpret_cast<const IPHdr*>(raw_ip_data);
+ if (h4->get_ver() == 4)
+ {
+ set(h4);
+ return true;
+ }
+
+ const ipv6::IP6RawHdr* h6 =
+ reinterpret_cast<const ipv6::IP6RawHdr*>(raw_ip_data);
+
+ if (h6->get_ver() != 6)
+ return false;
+
+ set(h6);
+ return true;
+}
+
+const sfip_t* IpApi::get_src()
+{
+ if (src_p)
+ return src_p;
+
+ if(ip4h)
+ {
+ src.family = AF_INET;
+ src.bits = 32;
+
+ // TODO: Make this a pointer rather than copying
+ // will likely need to change Snort++
+ src.ip32[0] = *(uint32_t*)(&ip4h->ip_src);
+ std::memset(&(src.ip32[1]), 0, 12);
+ }
+ else if (ip6h)
+ {
+ src.family = AF_INET6;
+ src.bits = 128;
+
+ std::memcpy(&(src.ip8), &(ip6h->ip6_src), 16);
+ }
+ else
+ {
+ return nullptr;
+ }
+
+ src_p = &src;
+ return src_p;
+}
+
+
+const sfip_t* IpApi::get_dst()
+{
+ if (dst_p)
+ return dst_p;
+
+ if(ip4h)
+ {
+ dst.family = AF_INET;
+ dst.bits = 32;
+
+ // TODO: Make this a pointer rather than copying
+ // will likely need to change Snort++
+ dst.ip32[0] = *(uint32_t*)(&ip4h->ip_dst);
+ std::memset(&(dst.ip32[1]), 0, 12);
+ }
+ else if (ip6h)
+ {
+ dst.family = AF_INET6;
+ dst.bits = 128;
+ std::memcpy(&(dst.ip8), &(ip6h->ip6_dst), 16);
+ }
+ else
+ {
+ return nullptr;
+ }
+
+ dst_p = &dst;
+ return dst_p;
+
+}
+
+uint32_t IpApi::id(const Packet* const p)
+{
+ if (ip4h)
+ return ip4h->get_id();
+
+ // ensure we have an ipv6 frag
+ if (p->ip6_extension_count == 0 || p->ip_frag_start == 0)
+ return 0;
+
+ const IP6Frag* const frag_hdr = reinterpret_cast<const IP6Frag* const>(
+ p->ip6_extensions[p->ip6_frag_index].data);
+
+ return frag_hdr->get_id();
+}
+
+uint16_t IpApi::off(const Packet* const p)
+{
+ if (ip4h)
+ return ip4h->get_id();
+
+ // ensure we have an ipv6 frag
+ if (p->ip6_extension_count == 0 || p->ip_frag_start == 0)
+ return 0;
+
+ const IP6Frag* const frag_hdr = reinterpret_cast<const IP6Frag* const>(
+ p->ip6_extensions[p->ip6_frag_index].data);
+
+ return frag_hdr->get_off();
+}
+
+
+} // namespace protocols
--- /dev/null
+/*
+** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License Version 2 as
+** published by the Free Software Foundation. You may not use, modify or
+** distribute this program under any other version of the GNU General
+** Public License.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+// ip.h author Josh Rosenbaum <jrosenba@cisco.com>
+
+#ifndef WIN32
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#else /* !WIN32 */
+#include <netinet/in_systm.h>
+#ifndef IFNAMSIZ
+#define IFNAMESIZ MAX_ADAPTER_NAME
+#endif /* !IFNAMSIZ */
+#endif /* !WIN32 */
+
+#include <cstring>
+
+#include "protocols/ipv4.h"
+#include "protocols/ipv6.h"
+#include "sfip/sfip_t.h"
+
+#ifndef IP_H
+#define IP_H
+
+class Packet;
+
+namespace ip
+{
+
+// keeping this as a class to avoid confusion.
+class IpApi
+{
+public:
+// IpApi(); constructor and destructor MUST remain a trivial. Adding
+// ~IpApi(); any non-trivial code will cause a compilation failure.
+
+ void set(const IPHdr* h4);
+ void set(const ipv6::IP6RawHdr* h6);
+ bool set(const uint8_t* raw_ip_data);
+ void reset();
+ const sfip_t* get_src();
+ const sfip_t* get_dst();
+ uint32_t id(const Packet* const p);
+ uint16_t off(const Packet* const p);
+
+
+ inline uint16_t tos()
+ { return ip4h ? ip4h->get_tos() : ip6h ? ip6h->get_tos() : 0; }
+
+ inline uint8_t ttl()
+ { return ip4h ? ip4h->get_ttl() : ip6h ? ip6h->get_hop_lim() : 0; }
+
+ inline uint8_t proto()
+ { return ip4h ? ip4h->get_proto() : ip6h ? ip6h->get_next() : 0; }
+
+ inline uint16_t len()
+ { return ip4h ? ip4h->get_len() : ip6h ? ip6h->get_len() : 0; }
+
+ inline uint8_t hlen()
+ { return ip4h ? ip4h->get_hlen() : ip6h ? ip6h->get_hlen() : 0; }
+
+ inline uint8_t ver()
+ { return ip4h ? ip4h->get_ver() : ip6h ? ip6h->get_ver() : 0; }
+
+
+private:
+ sfip_t src;
+ sfip_t dst;
+ const sfip_t* src_p;
+ const sfip_t* dst_p;
+ const IPHdr* ip4h;
+ const ipv6::IP6RawHdr* ip6h;
+};
+
+} // namespace ip
+
+#endif
*/
-#ifndef IPV4_H
-#define IPV4_H
-
#include <cstdint>
#include "sfip/sfip_t.h"
#include "protocols/protocol_ids.h" // include ipv4 protocol numbers
+
+
+#ifndef IPV4_H
+#define IPV4_H
+
#define ETHERNET_TYPE_IP 0x0800
#ifndef IP_MAXPACKET
#endif /* IP_MAXPACKET */
-namespace ipv4
+namespace ip
{
namespace detail
{
/* ip option type codes */
-const uint32_t IP4_THIS_NET = 0x00; // msb
-const uint32_t IP4_MULTICAST = 0x0E; // ms nibble
-const uint32_t IP4_RESERVED = 0x0F; // ms nibble
-const uint32_t IP4_LOOPBACK = 0x7F; // msb
-const uint32_t IP4_BROADCAST = 0xffffffff;
-const uint8_t IP_HEADER_LEN = 20;
+constexpr uint32_t IP4_THIS_NET = 0x00; // msb
+constexpr uint32_t IP4_MULTICAST = 0x0E; // ms nibble
+constexpr uint32_t IP4_RESERVED = 0x0F; // ms nibble
+constexpr uint32_t IP4_LOOPBACK = 0x7F; // msb
+constexpr uint32_t IP4_BROADCAST = 0xffffffff;
} // namespace detail
+// not included in details since this should not be hidden
+constexpr uint8_t IP4_HEADER_LEN = 20;
enum class IPOptionCodes : std::uint8_t {
uint8_t code;
uint8_t len; /* length of the data section */
const uint8_t *data;
+
+ inline bool is_opt_rtralt() const
+ { return code == static_cast<uint8_t>(IPOptionCodes::RTRALT); }
+
+ inline bool is_opt_ts() const
+ { return code == static_cast<uint8_t>(IPOptionCodes::TS); }
+
+ inline bool is_opt_rr() const
+ { return code == static_cast<uint8_t>(IPOptionCodes::RR); }
};
// This must be a standard layour struct!
uint8_t ip_ttl; /* time to live field */
uint8_t ip_proto; /* datagram protocol */
uint16_t ip_csum; /* checksum */
- struct in_addr ip_src; /* source IP */
- struct in_addr ip_dst; /* dest IP */
+ in_addr ip_src; /* source IP */
+ in_addr ip_dst; /* dest IP */
+
+ inline uint8_t get_hlen() const
+ { return ip_verhl & 0x0f; }
+
+ inline uint8_t get_ver() const
+ { return ((ip_verhl & 0xf0) >> 4); }
+
+ inline uint8_t get_tos() const
+ { return ip_tos; };
+
+ inline uint16_t get_len() const
+ { return ip_len; }
+
+ inline uint32_t get_id() const
+ { return (uint32_t)ip_id; }
+
+ inline uint16_t get_off() const
+ { return ip_off; }
+
+ inline uint8_t get_ttl() const
+ { return ip_ttl; }
+
+ inline uint8_t get_proto() const
+ { return ip_proto; }
+
+ inline uint16_t get_csum() const
+ { return ip_csum; }
+
+ inline const in_addr* get_src() const
+ { return &ip_src; }
+
+ inline const in_addr* get_dst() const
+ { return &ip_dst; }
} ;
return false;
}
-
-static inline uint16_t prot_id()
-{
- return IPPROTO_ID_IPIP;
-}
-
-static inline int ethertype_ip()
-{
- return ETHERTYPE_IPV4;
-}
-
static inline bool is_broadcast(uint32_t addr)
{
return (addr == detail::IP4_BROADCAST);
return (addr == detail::IP4_MULTICAST);
}
-static inline bool is_opt_rr(IPOptionCodes code)
-{
- return (code == IPOptionCodes::RR);
-}
-
-static inline bool is_opt_rr(uint8_t code)
-{
- return (static_cast<IPOptionCodes>(code) == IPOptionCodes::RR);
-}
-
-static inline bool is_opt_rtralt(IPOptionCodes code)
-{
- return (code == IPOptionCodes::RTRALT);
-}
-
-static inline bool is_opt_rtralt(uint8_t code)
-{
- return (static_cast<IPOptionCodes>(code) == IPOptionCodes::RTRALT);
-}
-
-static inline bool is_opt_ts(IPOptionCodes code)
-{
- return (code == IPOptionCodes::TS);
-}
-
-static inline bool is_opt_ts(uint8_t code)
-{
- return (static_cast<IPOptionCodes>(code) == IPOptionCodes::TS);
-}
-
-static inline bool is_ethertype_ip(int proto)
-{
- return (proto == ETHERTYPE_IPV4);
-}
-
-static inline bool is_ipv4(IPHdr* p)
-{
- return (p->ip_verhl >> 4) == 4;
-}
-
-static inline bool is_ipv4(const IP4Hdr* p)
-{
- return (p->ip_verhl >> 4) == 4;
-}
-
static inline bool is_ipv4(uint8_t ch)
{
return (ch >> 4) == 4;
return (p->ip_verhl & 0xf0) >> 4;
}
-static inline uint8_t hdr_len()
-{
- return detail::IP_HEADER_LEN;
-}
-
static inline bool is_loopback(uint8_t addr)
{
return addr == detail::IP4_LOOPBACK;
p->ip_verhl = (unsigned char)(((p)->ip_verhl & 0xf0) | (value & 0x0f));
}
-} /* namespace ipv4 */
+} /* namespace ip */
/* tcpdump shows us the way to cross platform compatibility */
/* we need to change them as well as get them */
// TYPEDEF WHICH NEED TO BE DELETED
-typedef ipv4::IPHdr IPHdr;
-typedef ipv4::IP4Hdr IP4Hdr;
+typedef ip::IPHdr IPHdr;
+typedef ip::IP4Hdr IP4Hdr;
-const uint8_t IPOPT_EOL = 0x00;
-const uint8_t IPOPT_NOP = 0x01;
-const uint8_t IPOPT_RR = 0x07;
-const uint8_t IPOPT_TS = 0x44;
-const uint8_t IPOPT_SECURITY = 0x82;
-const uint8_t IPOPT_LSRR = 0x83;
-const uint8_t IPOPT_LSRR_E = 0x84;
-const uint8_t IPOPT_ESEC = 0x85;
-const uint8_t IPOPT_SATID = 0x88;
-const uint8_t IPOPT_SSRR = 0x89;
-const uint8_t IPOPT_RTRALT = 0x94;
-const uint8_t IPOPT_ANY = 0xff;
+constexpr uint8_t IPOPT_EOL = 0x00;
+constexpr uint8_t IPOPT_NOP = 0x01;
+constexpr uint8_t IPOPT_RR = 0x07;
+constexpr uint8_t IPOPT_TS = 0x44;
+constexpr uint8_t IPOPT_SECURITY = 0x82;
+constexpr uint8_t IPOPT_LSRR = 0x83;
+constexpr uint8_t IPOPT_LSRR_E = 0x84;
+constexpr uint8_t IPOPT_ESEC = 0x85;
+constexpr uint8_t IPOPT_SATID = 0x88;
+constexpr uint8_t IPOPT_SSRR = 0x89;
+constexpr uint8_t IPOPT_RTRALT = 0x94;
+constexpr uint8_t IPOPT_ANY = 0xff;
-#define IP_HEADER_LEN ipv4::hdr_len()
+/* #define IP_HEADER_LEN ip::ip4_hdr_len() */
#endif
namespace detail
{
-const uint16_t ETHERNET_TYPE_IPV6 = 0x86dd;
-const uint16_t IPV6_PROT_ID = 41;
-const uint8_t IP6_HEADER_LEN = 40;
-const uint8_t IP6_MULTICAST = 0xFF; // first/most significant octet
-const uint32_t MIN_EXT_LEN = 8;
+constexpr uint8_t IP6_HEADER_LEN = 40;
+constexpr uint8_t IP6_MULTICAST = 0xFF; // first/most significant octet
+constexpr uint32_t MIN_EXT_LEN = 8;
} // namespace
uint8_t ip6f_reserved; /* reserved field */
uint16_t ip6f_offlg; /* offset, reserved, and flag */
uint32_t ip6f_ident; /* identification */
-} ;
+
+ inline uint32_t get_id() const
+ { return ip6f_ident; }
+
+ inline uint16_t get_off() const
+ { return ip6f_offlg; }
+};
struct IP6RawHdr
uint8_t ip6_next; /* next header */
uint8_t ip6_hoplim; /* hop limit */
- struct in6_addr ip6_src; /* source address */
- struct in6_addr ip6_dst; /* destination address */
+ in6_addr ip6_src; /* source address */
+ in6_addr ip6_dst; /* destination address */
+
+ inline const in6_addr* get_src() const
+ { return &ip6_src; }
+
+ inline const in6_addr* get_dst() const
+ { return &ip6_dst; }
+
+ inline uint16_t get_tos() const
+ { return (uint16_t)((ntohl(ip6_vtf) & 0x0FF00000) >> 20); }
+
+ inline uint8_t get_hop_lim() const
+ { return ip6_hoplim; }
+
+ inline uint16_t get_len() const
+ { return ip6_payload_len; }
+
+ inline uint8_t get_next() const
+ { return ip6_next; }
+
+ inline uint8_t get_ver() const
+ { return (uint8_t)(ntohl(ip6_vtf) >> 28); }
+
+ inline uint8_t get_hdr_len() const
+ { return (uint8_t) detail::IP6_HEADER_LEN; }
+
+ // becaise Snort expects this in terms of 32 bit words.
+ inline uint8_t get_hlen() const
+ { return detail::IP6_HEADER_LEN / 4; }
+
};
+
struct IP6Hdr
{
uint32_t vcl; /* version, class, and label */
return detail::IP6_HEADER_LEN;
}
-inline uint16_t ethertype()
-{
- return detail::ETHERNET_TYPE_IPV6;
-}
-
-inline uint16_t prot_id()
-{
- return detail::IPV6_PROT_ID;
-}
-
inline bool is_multicast(uint8_t addr)
{
return addr == detail::IP6_MULTICAST;
#include "protocols/packet.h"
+#include "protocols/layer.h"
#include "protocols/ipv4.h"
#include "protocols/ipv6.h"
+#include "protocols/ip.h"
namespace layer
{
-static inline const uint8_t *find_layer(const Layer *lyr,
+static inline const uint8_t* find_outer_layer(const Layer* lyr,
uint8_t num_layers,
uint16_t prot_id)
{
- for(int i = num_layers - 1; i >= 0 ; i--)
+ for(int i = 0; i < num_layers ; i++)
{
if (lyr->prot_id == prot_id)
return lyr->start;
return nullptr;
}
-static inline const uint8_t *find_layer(const Layer *lyr,
+static inline const uint8_t* find_inner_layer(const Layer* lyr,
+ uint8_t num_layers,
+ uint16_t prot_id)
+{
+ int tmp = num_layers-1;
+ lyr = &lyr[tmp];
+
+ for(int i = tmp; i >= 0 ; i--)
+ {
+ if (lyr->prot_id == prot_id)
+ return lyr->start;
+ lyr--;
+ }
+ return nullptr;
+}
+
+static inline const uint8_t* find_inner_layer(const Layer* lyr,
uint8_t num_layers,
uint16_t prot_id1,
uint16_t prot_id2)
{
+ int tmp = num_layers-1;
+ lyr = &lyr[tmp];
+
for(int i = num_layers - 1; i >= 0; i--)
{
if (lyr->prot_id == prot_id1 ||
lyr->prot_id == prot_id2)
return lyr->start;
- lyr++;
+ lyr--;
}
return nullptr;
}
+
+const uint8_t* get_inner_layer(const Packet* p, uint16_t proto)
+{ return find_inner_layer(p->layers, p->num_layers, proto); }
+
+const uint8_t* get_outer_layer(const Packet* p, uint16_t proto)
+{ return find_outer_layer(p->layers, p->num_layers, proto); }
+
+
const arp::EtherARP* get_arp_layer(const Packet* const p)
{
uint8_t num_layers = p->num_layers;
const Layer *lyr = p->layers;
return reinterpret_cast<const arp::EtherARP*>(
- find_layer(lyr, num_layers, ETHERTYPE_ARP, ETHERTYPE_REVARP));
+ find_inner_layer(lyr, num_layers, ETHERTYPE_ARP, ETHERTYPE_REVARP));
}
const gre::GREHdr* get_gre_layer(const Packet* const p)
const Layer *lyr = p->layers;
return reinterpret_cast<const gre::GREHdr*>(
- find_layer(lyr, num_layers, IPPROTO_ID_GRE));
+ find_inner_layer(lyr, num_layers, IPPROTO_ID_GRE));
}
const eapol::EtherEapol* get_eapol_layer(const Packet* const p)
const Layer *lyr = p->layers;
return reinterpret_cast<const eapol::EtherEapol*>(
- find_layer(lyr, num_layers, ETHERTYPE_EAPOL));
+ find_inner_layer(lyr, num_layers, ETHERTYPE_EAPOL));
}
const vlan::VlanTagHdr* get_vlan_layer(const Packet* const p)
const Layer *lyr = p->layers;
return reinterpret_cast<const vlan::VlanTagHdr*>(
- find_layer(lyr, num_layers, ETHERTYPE_8021Q));
+ find_inner_layer(lyr, num_layers, ETHERTYPE_8021Q));
}
const eth::EtherHdr* get_eth_layer(const Packet* const p)
// First, search for the inner eth layer (transbridging)
const eth::EtherHdr* eh = reinterpret_cast<const eth::EtherHdr*>(
- find_layer(lyr, num_layers, ETHERTYPE_TRANS_ETHER_BRIDGING));
+ find_inner_layer(lyr, num_layers, ETHERTYPE_TRANS_ETHER_BRIDGING));
// if no inner eth layer, assume root layer is eth (callers job to confirm)
return eh ? eh : reinterpret_cast<const eth::EtherHdr*>(get_root_layer(p));
return -1;
}
+bool set_api_ip_embed_icmp(Packet* const p)
+{ return set_api_ip_embed_icmp(p, p->ip_api); }
+
+bool set_api_ip_embed_icmp(const Packet* p, ip::IpApi& api)
+{
+ int num_layers = p->num_layers - 1;
+ const Layer* lyr = &p->layers[num_layers];
+
+ for(int i = num_layers; i >= 0; i--)
+ {
+ if (lyr->prot_id == IP_EMBEDDED_IN_ICMP4)
+ {
+ const ip::IPHdr* ip4h =
+ reinterpret_cast<const ip::IPHdr*>(lyr->start);
+ api.set(ip4h);
+ return true;
+ }
+ else if (lyr->prot_id == IP_EMBEDDED_IN_ICMP6)
+ {
+ const ipv6::IP6RawHdr* ip6h =
+ reinterpret_cast<const ipv6::IP6RawHdr*>(lyr->start);
+ api.set(ip6h);
+ return true;
+ }
+
+ lyr--;
+ }
+
+ api.reset();
+ return false;
+}
+
+const uint8_t* get_prot_embed_icmp(const Packet* const p)
+{
+ return find_inner_layer(p->layers,
+ p->num_layers,
+ PROT_EMBEDDED_IN_ICMP);
+}
+
+const tcp::TCPHdr* get_tcp_embed_icmp(const Packet* const p)
+{
+ return reinterpret_cast<const tcp::TCPHdr*>(
+ get_prot_embed_icmp(p));
+}
+
+const udp::UDPHdr* get_udp_embed_icmp(const Packet* const p)
+{
+ return reinterpret_cast<const udp::UDPHdr*>(
+ get_prot_embed_icmp(p));
+}
+
+const icmp::ICMPHdr* get_icmp_embed_icmp(const Packet* const p)
+{
+ return reinterpret_cast<const icmp::ICMPHdr*>(
+ get_prot_embed_icmp(p));
+}
+
+
} // namespace layer
#include "codecs/sf_protocols.h"
-
struct Layer {
uint16_t prot_id;
PROTO_ID proto;
struct EtherHdr;
}
+namespace ip
+{
+class IpApi;
+}
+
+namespace tcp
+{
+struct TCPHdr;
+}
+
+namespace udp
+{
+struct UDPHdr;
+}
+
+namespace icmp
+{
+struct ICMPHdr;
+}
namespace layer
{
// all of these functions will begin search from layer 0,
// and will return the first function they find.
+const uint8_t* get_inner_layer(const Packet*, uint16_t proto);
+const uint8_t* get_outer_layer(const Packet*, uint16_t proto);
const arp::EtherARP* get_arp_layer(const Packet*);
const eth::EtherHdr* get_eth_layer(const Packet*);
const uint8_t* get_root_layer(const Packet* const);
+
+// ICMP with Embedded IP layer
+
+
+// Sets the Packet's api to be the IP layer which is
+// embedded inside an ICMP layer.
+// RETURN:
+// true - ip layer found and api set
+// false - ip layer NOT found, api reset
+bool set_api_ip_embed_icmp(const Packet*);
+bool set_api_ip_embed_icmp(const Packet*, ip::IpApi& api);
+
+// When a protocol is embedded in ICMP, this function
+// will return a pointer to the layer. Use the
+// proto_bits to determine what this layer is!
+const uint8_t* get_prot_embed_icmp(const Packet* const);
+const tcp::TCPHdr* get_tcp_embed_icmp(const Packet* const);
+const udp::UDPHdr* get_udp_embed_icmp(const Packet* const);
+const icmp::ICMPHdr* get_icmp_embed_icmp(const Packet* const);
+
+
int get_inner_ip_lyr(const Packet* const p);
uint16_t get_outer_ip_next_proto(const Packet* const);
#include "protocols/icmp4.h"
#include "protocols/icmp6.h"
#include "protocols/mpls.h"
+#include "protocols/ip.h"
/* D E F I N E S ************************************************************/
#define DEFAULT_MPLS_PAYLOADTYPE MPLS_PAYLOADTYPE_IPV4
#define DEFAULT_LABELCHAIN_LENGTH -1
-const int32_t MAX_PORTS = 65536;
-const uint16_t NUM_IP_PROTOS = 256;
-const int16_t SFTARGET_UNKNOWN_PROTOCOL = -1;
-const uint8_t IP_OPTMAX = 40;
-const uint8_t TCP_OPTLENMAX = 40; /* (((2^4) - 1) * 4 - TCP_HEADER_LEN) */
-const uint8_t IP6_EXTMAX = 8;
-const uint8_t MIN_TTL = 64;
-const uint8_t MAX_TTL = 255;
-const uint8_t LAYER_MAX = 32;
+constexpr int32_t MAX_PORTS = 65536;
+constexpr uint16_t NUM_IP_PROTOS = 256;
+constexpr int16_t SFTARGET_UNKNOWN_PROTOCOL = -1;
+constexpr uint8_t IP_OPTMAX = 40;
+constexpr uint8_t TCP_OPTLENMAX = 40; /* (((2^4) - 1) * 4 - TCP_HEADER_LEN) */
+constexpr uint8_t IP6_EXTMAX = 8;
+constexpr uint8_t MIN_TTL = 64;
+constexpr uint8_t MAX_TTL = 255;
+constexpr uint8_t LAYER_MAX = 32;
//vvv-----------------------------
- const IPHdr *iph, *orig_iph;/* and orig. headers for ICMP_*_UNREACH family */
+ const IPHdr *iph;
const IPHdr *inner_iph; /* if IP-in-IP, this will be the inner IP header */
const IPHdr *outer_iph; /* if IP-in-IP, this will be the outer IP header */
- const TCPHdr *tcph, *orig_tcph;
- const udp::UDPHdr *udph, *orig_udph;
+ const tcp::TCPHdr *tcph;
+ const udp::UDPHdr *udph;
const udp::UDPHdr *outer_udph; /* if Teredo + UDP, this will be the outer UDP header */
- const ICMPHdr *icmph, *orig_icmph;
+ const ICMPHdr *icmph;
const uint8_t *data; /* packet payload pointer */
const uint8_t *ip_data; /* IP payload pointer */
Flow* flow; /* for session tracking */
//vvv-----------------------------
- ipv4::IP4Hdr *ip4h;
+ ip::IP4Hdr *ip4h;
ipv6::IP6Hdr *ip6h;
- icmp6::ICMP6Hdr *icmp6h;
IPH_API* iph_api;
- IPH_API* orig_iph_api;
IPH_API* outer_iph_api;
int family;
- int orig_family;
int outer_family;
//^^^-----------------------------
//vvv-----------------------------
uint16_t sp; /* source port (TCP/UDP) */
uint16_t dp; /* dest port (TCP/UDP) */
- uint16_t orig_sp; /* source port (TCP/UDP) of original datagram */
- uint16_t orig_dp; /* dest port (TCP/UDP) of original datagram */
//^^^-----------------------------
// and so on ...
const DAQ_PktHdr_t *pkth; // packet meta data
const uint8_t *pkt; // raw packet data
- ipv4::IpOptions ip_options[IP_OPTMAX]; /* ip options decode structure */
+ ip::IpOptions ip_options[IP_OPTMAX]; /* ip options decode structure */
Options tcp_options[TCP_OPTLENMAX]; /* tcp options decode struct */
IP6Option ip6_extensions[IP6_EXTMAX]; /* IPv6 Extension References */
const ipv6::IP6RawHdr* raw_ip6h; // innermost raw ip6 header
Layer layers[LAYER_MAX]; /* decoded encapsulations */
- ipv4::IP4Hdr inner_ip4h;
+ ip::IP4Hdr inner_ip4h;
ipv6::IP6Hdr inner_ip6h;
- ipv4::IP4Hdr outer_ip4h;
+ ip::IP4Hdr outer_ip4h;
ipv6::IP6Hdr outer_ip6h;
+ ip::IpApi ip_api;
MplsHdr mplsHdr;
#define PROTO_BIT__MPLS 0x0080
#define PROTO_BIT__VLAN 0x0100
#define PROTO_BIT__ETH 0x0200
-#define PROTO_BIT__FREE 0x7c00
+#define PROTO_BIT__TCP_EMBED_ICMP 0x0400
+#define PROTO_BIT__UDP_EMBED_ICMP 0x0800
+#define PROTO_BIT__ICMP_EMBED_ICMP 0x1000
+#define PROTO_BIT__FREE 0x6000
#define PROTO_BIT__OTHER 0x8000
#define PROTO_BIT__ALL 0xffff
#define DECODE__MF 0x02 /* more fragments flag */
#define DECODE__DF 0x04 /* don't fragment flag */
#define DECODE__RF 0x08 /* IP reserved bit */
-#define DECODE__ESP 0x10 /* flag to indicate an ESP layer has been seen */
-#define DECODE__UNSURE_ENCAP 0x20 /* packet may have incorrect encapsulation layer. */
- /* don't alert if "next layer" is invalid. */
+#define DECODE__TRUST_ON_FAIL 0x10 /* if decode fails, set the PKT_TRUST flag */
+#define DECODE__UNSURE_ENCAP 0x20 /* packet may have incorrect encapsulation layer. */
+ /* don't alert if "next layer" is invalid. */
#define DECODE__FREE 0xC0
#define IsIP(p) (IPH_IS_VALID(p))
* http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
*/
-const uint16_t IPPROTO_ID_HOPOPTS = 0;
-const uint16_t IPPROTO_ID_ICMPV4 = 1;
-const uint16_t IPPROTO_ID_IPIP = 4;
-const uint16_t IPPROTO_ID_IPV6 = 41;
-const uint16_t IPPROTO_ID_ROUTING = 43;
-const uint16_t IPPROTO_ID_FRAGMENT = 44;
-const uint16_t IPPROTO_ID_GRE = 47;
-const uint16_t IPPROTO_ID_ESP = 50;
-const uint16_t IPPROTO_ID_AH = 51; // RFC 4302
-const uint16_t IPPROTO_ID_ICMPV6 = 58;
-const uint16_t IPPROTO_ID_NONEXT = 59;
-const uint16_t IPPROTO_ID_DSTOPTS = 60;
+constexpr uint16_t IPPROTO_ID_HOPOPTS = 0;
+constexpr uint16_t IPPROTO_ID_ICMPV4 = 1;
+constexpr uint16_t IPPROTO_ID_IPIP = 4;
+constexpr uint16_t IPPROTO_ID_IPV6 = 41;
+constexpr uint16_t IPPROTO_ID_ROUTING = 43;
+constexpr uint16_t IPPROTO_ID_FRAGMENT = 44;
+constexpr uint16_t IPPROTO_ID_GRE = 47;
+constexpr uint16_t IPPROTO_ID_ESP = 50;
+constexpr uint16_t IPPROTO_ID_AH = 51; // RFC 4302
+constexpr uint16_t IPPROTO_ID_ICMPV6 = 58;
+constexpr uint16_t IPPROTO_ID_NONEXT = 59;
+constexpr uint16_t IPPROTO_ID_DSTOPTS = 60;
/*
* Undefined Protocol!
*/
-const uint16_t FINISHED_DECODE = 0x0100; // Indicates Codecs have succesfully decoded packet
-const uint16_t PROTOCOL_TEREDO = 0x0101;
-const uint16_t PROTOCOL_GTP = 0x0102;
+constexpr uint16_t FINISHED_DECODE = 0x0100; // Indicates Codecs have succesfully decoded packet
+constexpr uint16_t PROTOCOL_TEREDO = 0x0101;
+constexpr uint16_t PROTOCOL_GTP = 0x0102;
+constexpr uint16_t IP_EMBEDDED_IN_ICMP4 = 0x0103;
+constexpr uint16_t IP_EMBEDDED_IN_ICMP6 = 0x0104;
+constexpr uint16_t PROT_EMBEDDED_IN_ICMP = 0x0105;
*/
-const uint16_t ETHERTYPE_TRANS_ETHER_BRIDGING = 0x6558;
-const uint16_t ETHERTYPE_IPV4 = 0x0800;
-const uint16_t ETHERTYPE_REVARP = 0x8035;
-const uint16_t ETHERTYPE_ARP = 0x0806;
-const uint16_t ETHERTYPE_8021Q = 0x8100;
-const uint16_t ETHERTYPE_IPX = 0x8137;
-const uint16_t ETHERTYPE_IPV6 = 0x86dd;
-const uint16_t ETHERTYPE_PPP = 0x880B;
-const uint16_t ETHERTYPE_EAPOL = 0x888e;
+constexpr uint16_t ETHERTYPE_TRANS_ETHER_BRIDGING = 0x6558;
+constexpr uint16_t ETHERTYPE_IPV4 = 0x0800;
+constexpr uint16_t ETHERTYPE_REVARP = 0x8035;
+constexpr uint16_t ETHERTYPE_ARP = 0x0806;
+constexpr uint16_t ETHERTYPE_8021Q = 0x8100;
+constexpr uint16_t ETHERTYPE_IPX = 0x8137;
+constexpr uint16_t ETHERTYPE_IPV6 = 0x86dd;
+constexpr uint16_t ETHERTYPE_PPP = 0x880B;
+constexpr uint16_t ETHERTYPE_EAPOL = 0x888e;
#endif
-
-
namespace detail
{
-const uint8_t TCP_HEADER_LEN = 20;
+constexpr uint8_t TCP_HEADER_LEN = 20;
} // namespace detail
#define TCP_HEADER_LEN tcp::hdr_len()
-#define TCPHdr tcp::TCPHdr
-
#endif /* TCP_H */
#define GET_SRC_IP(p) ((p)->iph_api->iph_ret_src(p))
#define GET_DST_IP(p) ((p)->iph_api->iph_ret_dst(p))
-#define GET_ORIG_SRC(p) ((p)->orig_iph_api->orig_iph_ret_src(p))
-#define GET_ORIG_DST(p) ((p)->orig_iph_api->orig_iph_ret_dst(p))
-
/* These are here for backwards compatibility */
#define GET_SRC_ADDR(x) GET_SRC_IP(x)
#define GET_DST_ADDR(x) GET_DST_IP(x)
#define GET_IPH_VER(p) (p)->iph_api->iph_ret_ver(p)
#define GET_IPH_PROTO(p) ((uint8_t)(IS_IP6(p) ? ((p)->ip6h->next) : ((p)->iph_api->iph_ret_proto(p))))
+
+#if 0
+
+#define GET_ORIG_SRC(p) ((p)->orig_iph_api->orig_iph_ret_src(p))
+#define GET_ORIG_DST(p) ((p)->orig_iph_api->orig_iph_ret_dst(p))
#define GET_ORIG_IPH_PROTO(p) (p)->orig_iph_api->orig_iph_ret_proto(p)
#define GET_ORIG_IPH_VER(p) (p)->orig_iph_api->orig_iph_ret_ver(p)
#define GET_ORIG_IPH_LEN(p) (p)->orig_iph_api->orig_iph_ret_len(p)
#define GET_ORIG_IPH_OFF(p) (p)->orig_iph_api->orig_iph_ret_off(p)
#define GET_ORIG_IPH_PROTO(p) (p)->orig_iph_api->orig_iph_ret_proto(p)
+#endif
+
/* XXX make sure these aren't getting confused with sfip_is_valid within the code */
#define IPH_IS_VALID(p) iph_is_valid(p)
return (p->iph->ip_verhl & 0xf0) >> 4;
}
+#if 0
uint8_t orig_ip4_ret_ver(const Packet *p)
{
return (p->orig_iph->ip_verhl & 0xf0) >> 4;
}
+#endif
uint8_t ip4_ret_hlen(const Packet *p)
{
uint8_t orig_ip4_ret_hlen(const Packet *p)
{
- return p->orig_iph->ip_verhl & 0x0f;
+ return 0;
+// return p->orig_iph->ip_verhl & 0x0f;
}
uint8_t ip6_ret_hlen(const Packet*)
ip4_ret_off,
ip4_ret_ver,
ip4_ret_hlen,
-
+#if 0
orig_ip4_ret_src,
orig_ip4_ret_dst,
orig_ip4_ret_tos,
orig_ip4_ret_off,
orig_ip4_ret_ver,
orig_ip4_ret_hlen,
-
+#endif
IPH_API_V4
};
ip6_ret_off,
ip6_ret_ver,
ip6_ret_hlen,
-
+#if 0
orig_ip6_ret_src,
orig_ip6_ret_dst,
orig_ip6_ret_toc,
orig_ip6_ret_off,
orig_ip6_ret_ver,
orig_ip6_ret_hlen,
-
+#endif
IPH_API_V6
};
p->family = family;
}
- else
- {
- if(family == AF_INET)
- p->orig_iph_api = &ip4;
- else
- p->orig_iph_api = &ip6;
-
- p->orig_family = family;
- }
}
void set_callbacks(Packet* p, int family, char orig)
uint8_t (*iph_ret_ver)(const Packet*);
uint8_t (*iph_ret_hlen)(const Packet*);
+#if 0
sfip_t * (*orig_iph_ret_src)(const Packet*);
sfip_t * (*orig_iph_ret_dst)(const Packet*);
uint16_t (*orig_iph_ret_tos)(const Packet*);
uint16_t (*orig_iph_ret_off)(const Packet*);
uint8_t (*orig_iph_ret_ver)(const Packet*);
uint8_t (*orig_iph_ret_hlen)(const Packet*);
-
+#endif
char ver;
} IPH_API;
#define NO_IP 0
void sfiph_build(Packet*, const void *hdr, int family);
-void sfiph_orig_build(Packet*, const void *hdr, int family);
/* Sets the callbacks to point at the family selected by
* * "family". "family" is either AF_INET or AF_INET6 */
#include "profiler.h"
#include "protocols/layer.h"
#include "protocols/vlan.h"
+#include "protocols/ip.h"
THREAD_LOCAL SessionStats icmpStats;
THREAD_LOCAL ProfileStats icmp_perf_stats;
{
/* Handle ICMP unreachable */
FlowKey skey;
- Flow *ssn = NULL;
+ Flow* ssn = NULL;
uint16_t sport;
uint16_t dport;
- sfip_t *src;
- sfip_t *dst;
+ const sfip_t* src;
+ const sfip_t* dst;
+ ip::IpApi iph;
- /* No "orig" IP Header */
- if (!p->orig_iph)
+ /* Set the Ip API to the embedded IP Header. */
+ if (!layer::set_api_ip_embed_icmp(p, iph))
return 0;
- /* Get TCP/UDP/ICMP session from original protocol/port info
- * embedded in the ICMP Unreach message. This is already decoded
- * in p->orig_foo. TCP/UDP ports are decoded as p->orig_sp/dp.
+ /* Get IP/TCP/UDP/ICMP session from original protocol/port info
+ * embedded in the ICMP Unreach message.
*/
- skey.protocol = GET_ORIG_IPH_PROTO(p);
- sport = p->orig_sp;
- dport = p->orig_dp;
+ skey.protocol = iph.proto();
+ src = iph.get_src();
+ dst = iph.get_dst();
+
+
+ if (p->proto_bits & PROTO_BIT__TCP_EMBED_ICMP)
+ {
+ const tcp::TCPHdr* tcph = layer::get_tcp_embed_icmp(p);
+ sport = ntohs(tcph->th_sport);
+ dport = ntohs(tcph->th_dport);
+ }
+ else if (p->proto_bits & PROTO_BIT__UDP_EMBED_ICMP)
+ {
+ const udp::UDPHdr* udph = layer::get_udp_embed_icmp(p);
+
+ sport = ntohs(udph->uh_sport);
+ dport = ntohs(udph->uh_dport);
+ }
+ else
+ {
+ sport = 0;
+ dport = 0;
+ }
+
- src = GET_ORIG_SRC(p);
- dst = GET_ORIG_DST(p);
if (sfip_fast_lt6(src, dst))
{
COPY4(skey.ip_h, dst->ip32);
skey.port_h = dport;
}
- else if (IP_EQUALITY(GET_ORIG_SRC(p), GET_ORIG_DST(p)))
+ else if (IP_EQUALITY(iph.get_src(), iph.get_dst()))
{
COPY4(skey.ip_l, src->ip32);
COPY4(skey.ip_h, skey.ip_l);
DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
"Adjusting IP Header to %d bytes\n",
new_ip_hlen););
- ipv4::set_hlen((IPHdr *)dpkt->iph, new_ip_hlen>>2);
+ ip::set_hlen((IPHdr *)dpkt->iph, new_ip_hlen>>2);
ret = SafeMemcpy(rebuild_ptr, ft->ip_options_data,
ft->ip_options_len, rebuild_ptr, rebuild_end);
#include "tcp_module.h"
#include "stream/stream_splitter.h"
+using namespace tcp;
+
THREAD_LOCAL ProfileStats s5TcpPerfStats;
THREAD_LOCAL ProfileStats s5TcpNewSessPerfStats;
THREAD_LOCAL ProfileStats s5TcpStatePerfStats;