Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

detect: Recognize ERSPAN Type I packets #4627

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions src/decode-erspan.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2015 Open Information Security Foundation
/* Copyright (C) 2020 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
Expand Down Expand Up @@ -27,7 +27,7 @@
*
* \author Victor Julien <victor@inliniac.net>
*
* Decodes ERSPAN
* Decodes ERSPAN Types I and II
*/

#include "suricata-common.h"
Expand All @@ -40,10 +40,37 @@
#include "util-debug.h"

/**
* \brief Function to decode ERSPAN packets
* \brief Functions to decode ERSPAN Type I and II packets
*/

int DecodeERSPAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len, PacketQueue *pq)
bool g_erspan_typeI_enabled = false;

void DecodeERSPANConfig(void)
{
int enabled = 0;
if (ConfGetBool("decoder.erspan_typeI.enabled", &enabled) == 1) {
g_erspan_typeI_enabled = enabled == 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true instead of 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In 5.0.x, ConfGetBool returns an int

}
}

/**
* \brief ERSPAN Type I
*/
int DecodeERSPANTypeI(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
const uint8_t *pkt, uint32_t len, PacketQueue *pq)
{
if (unlikely(!g_erspan_typeI_enabled))
return TM_ECODE_FAILED;
jlucovsky marked this conversation as resolved.
Show resolved Hide resolved

StatsIncr(tv, dtv->counter_erspan);

return DecodeEthernet(tv, dtv, p, pkt, len, pq);
}

/**
* \brief ERSPAN Type II
*/
int DecodeERSPANTypeII(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len, PacketQueue *pq)
{
StatsIncr(tv, dtv->counter_erspan);

Expand Down
1 change: 1 addition & 0 deletions src/decode-erspan.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ typedef struct ErspanHdr_ {
uint32_t padding;
} __attribute__((__packed__)) ErspanHdr;

void DecodeERSPANConfig(void);
#endif /* __DECODE_ERSPAN_H__ */
16 changes: 12 additions & 4 deletions src/decode-gre.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2007-2013 Open Information Security Foundation
/* Copyright (C) 2007-2020 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
Expand Down Expand Up @@ -66,7 +66,7 @@ int DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *p
{
case GRE_VERSION_0:

/* GRE version 0 doenst support the fields below RFC 1701 */
/* GRE version 0 doesn't support the fields below RFC 1701 */

/**
* \todo We need to make sure this does not allow bypassing
Expand Down Expand Up @@ -130,7 +130,7 @@ int DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *p

case GRE_VERSION_1:

/* GRE version 1 doenst support the fields below RFC 1701 */
/* GRE version 1 doesn't support the fields below RFC 1701 */

/**
* \todo We need to make sure this does not allow bypassing
Expand Down Expand Up @@ -252,8 +252,16 @@ int DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *p
case ETHERNET_TYPE_ERSPAN:
{
if (pq != NULL) {
// Determine if it's Type I or Type II based on the flags in the GRE header.
// Type I: 0|0|0|0|0|00000|000000000|00000
// Type II: 0|0|0|1|0|00000|000000000|00000
// Seq
Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
len - header_len, DECODE_TUNNEL_ERSPAN, pq);
len - header_len,
GRE_FLAG_ISSET_SQ(p->greh) == 0 ?
DECODE_TUNNEL_ERSPANI :
DECODE_TUNNEL_ERSPANII,
pq);
if (tp != NULL) {
PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
PacketEnqueue(pq,tp);
Expand Down
17 changes: 10 additions & 7 deletions src/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* example we have DecodeIPV4() for IPv4 and DecodePPP() for
* PPP.
*
* These functions have all a pkt and and a len argument which
* These functions have all a pkt and a len argument which
* are respectively a pointer to the protocol data and the length
* of this protocol data.
*
Expand Down Expand Up @@ -88,8 +88,10 @@ int DecodeTunnel(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
return DecodeVLAN(tv, dtv, p, pkt, len, pq);
case DECODE_TUNNEL_ETHERNET:
return DecodeEthernet(tv, dtv, p, pkt, len, pq);
case DECODE_TUNNEL_ERSPAN:
return DecodeERSPAN(tv, dtv, p, pkt, len, pq);
case DECODE_TUNNEL_ERSPANII:
return DecodeERSPANTypeII(tv, dtv, p, pkt, len, pq);
case DECODE_TUNNEL_ERSPANI:
return DecodeERSPANTypeI(tv, dtv, p, pkt, len, pq);
default:
SCLogDebug("FIXME: DecodeTunnel: protocol %" PRIu32 " not supported.", proto);
break;
Expand All @@ -110,7 +112,7 @@ void PacketFree(Packet *p)
* \brief Finalize decoding of a packet
*
* This function needs to be call at the end of decode
* functions when decoding has been succesful.
* functions when decoding has been successful.
*
*/
void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Expand Down Expand Up @@ -287,7 +289,7 @@ Packet *PacketTunnelPktSetup(ThreadVars *tv, DecodeThreadVars *dtv, Packet *pare
SCReturnPtr(NULL, "Packet");
}

/* copy packet and set lenght, proto */
/* copy packet and set length, proto */
PacketCopyData(p, pkt, len);
p->recursion_level = parent->recursion_level + 1;
p->ts.tv_sec = parent->ts.tv_sec;
Expand Down Expand Up @@ -384,7 +386,7 @@ Packet *PacketDefragPktSetup(Packet *parent, const uint8_t *pkt, uint32_t len, u

/**
* \brief inform defrag "parent" that a pseudo packet is
* now assosiated to it.
* now associated to it.
*/
void PacketDefragPktSetupParent(Packet *parent)
{
Expand Down Expand Up @@ -646,7 +648,7 @@ void DecodeThreadVarsFree(ThreadVars *tv, DecodeThreadVars *dtv)
}

/**
* \brief Set data for Packet and set length when zeo copy is used
* \brief Set data for Packet and set length when zero copy is used
*
* \param Pointer to the Packet to modify
* \param Pointer to the data
Expand Down Expand Up @@ -730,6 +732,7 @@ void DecodeGlobalConfig(void)
{
DecodeTeredoConfig();
DecodeVXLANConfig();
DecodeERSPANConfig();
}

/**
Expand Down
13 changes: 8 additions & 5 deletions src/decode.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2007-2013 Open Information Security Foundation
/* Copyright (C) 2007-2020 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
Expand Down Expand Up @@ -161,7 +161,7 @@ typedef struct Address_ {
(a)->addr_data32[3] = 0; \
} while (0)

/* Set the IPv6 addressesinto the Addrs of the Packet.
/* Set the IPv6 addresses into the Addrs of the Packet.
* Make sure p->ip6h is initialized and validated. */
#define SET_IPV6_SRC_ADDR(p, a) do { \
(a)->family = AF_INET6; \
Expand Down Expand Up @@ -386,7 +386,7 @@ typedef struct PktProfiling_ {

#endif /* PROFILING */

/* forward declartion since Packet struct definition requires this */
/* forward declaration since Packet struct definition requires this */
struct PacketQueue_;

/* sizes of the members:
Expand Down Expand Up @@ -889,7 +889,8 @@ void CaptureStatsSetup(ThreadVars *tv, CaptureStats *s);

enum DecodeTunnelProto {
DECODE_TUNNEL_ETHERNET,
DECODE_TUNNEL_ERSPAN,
DECODE_TUNNEL_ERSPANII,
DECODE_TUNNEL_ERSPANI,
DECODE_TUNNEL_VLAN,
DECODE_TUNNEL_IPV4,
DECODE_TUNNEL_IPV6,
Expand Down Expand Up @@ -943,6 +944,8 @@ int DecodeVLAN(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint
int DecodeVXLAN(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t, PacketQueue *);
int DecodeMPLS(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t, PacketQueue *);
int DecodeERSPAN(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t, PacketQueue *);
int DecodeERSPANTypeII(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t, PacketQueue *);
int DecodeERSPANTypeI(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t, PacketQueue *);
int DecodeTEMPLATE(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t, PacketQueue *);

#ifdef UNITTESTS
Expand Down Expand Up @@ -1089,7 +1092,7 @@ void DecodeUnregisterCounters(void);
#define PKT_ALLOC (1<<3) /**< Packet was alloc'd this run, needs to be freed */
#define PKT_HAS_TAG (1<<4) /**< Packet has matched a tag */
#define PKT_STREAM_ADD (1<<5) /**< Packet payload was added to reassembled stream */
#define PKT_STREAM_EST (1<<6) /**< Packet is part of establised stream */
#define PKT_STREAM_EST (1<<6) /**< Packet is part of established stream */
#define PKT_STREAM_EOF (1<<7) /**< Stream is in eof state */
#define PKT_HAS_FLOW (1<<8)
#define PKT_PSEUDO_STREAM_END (1<<9) /**< Pseudo packet to end the stream */
Expand Down
3 changes: 3 additions & 0 deletions suricata.yaml.in
Original file line number Diff line number Diff line change
Expand Up @@ -1338,6 +1338,9 @@ decoder:
vxlan:
enabled: true
ports: $VXLAN_PORTS # syntax: '8472, 4789'
# ERSPAN Type I
erspan_typeI:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wonder if we should make this something like:

erspan:
  typeI:
    enabled: false

Also, wondering if we need to make sure this carries forward to newer releases. If the config has this explicitly disabled here, it should be respected in 6.0 as well right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. The intent of making it configurable is to provide control over (what might be) the additional packet load introduced by the back port.

Only Teredo and VXLAN decoding is configurable in 6.0.

For 6.0, I'd recommend that we detect the configuration setting and either

  1. Exit with an error message ("Deprecated setting" or similar)
  2. Issue a warning and continue execution ("Warning: ERSPAN Type I is no longer configurable")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue 3515 created to track.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Issue a warning and continue execution ("Warning: ERSPAN Type I is no longer configurable")

I think I'd prefer this approach.

enabled: false


##
Expand Down