1 /* Copyright (C) 2020 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \ingroup decode
20  *
21  * @{
22  */
23 
24 
25 /**
26  * \file
27  *
28  * \author Victor Julien <victor@inliniac.net>
29  *
30  * Decodes ERSPAN Types I and II
31  */
32 
33 #include "suricata-common.h"
34 #include "suricata.h"
35 #include "decode.h"
36 #include "decode-events.h"
37 #include "decode-erspan.h"
38 
39 #include "util-unittest.h"
40 #include "util-debug.h"
41 
42 /**
43  * \brief Functions to decode ERSPAN Type I and II packets
44  */
45 
46 /*
47  * \brief ERSPAN Type I was configurable in 5.0.x but is no longer configurable.
48  *
49  * Issue a warning if a configuration setting is found.
50  */
DecodeERSPANConfig(void)51 void DecodeERSPANConfig(void)
52 {
53     int enabled = 0;
54     if (ConfGetBool("decoder.erspan.typeI.enabled", &enabled) == 1) {
55         SCLogWarning(SC_WARN_ERSPAN_CONFIG,
56                      "ERSPAN Type I is no longer configurable and it is always"
57                      " enabled; ignoring configuration setting.");
58     }
59 }
60 
61 /**
62  * \brief ERSPAN Type I
63  */
DecodeERSPANTypeI(ThreadVars * tv,DecodeThreadVars * dtv,Packet * p,const uint8_t * pkt,uint32_t len)64 int DecodeERSPANTypeI(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
65                       const uint8_t *pkt, uint32_t len)
66 {
67     StatsIncr(tv, dtv->counter_erspan);
68 
69     return DecodeEthernet(tv, dtv, p, pkt, len);
70 }
71 
72 /**
73  * \brief ERSPAN Type II
74  */
DecodeERSPAN(ThreadVars * tv,DecodeThreadVars * dtv,Packet * p,const uint8_t * pkt,uint32_t len)75 int DecodeERSPAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
76 {
77     StatsIncr(tv, dtv->counter_erspan);
78 
79     if (len < sizeof(ErspanHdr)) {
80         ENGINE_SET_EVENT(p,ERSPAN_HEADER_TOO_SMALL);
81         return TM_ECODE_FAILED;
82     }
83     if (!PacketIncreaseCheckLayers(p)) {
84         return TM_ECODE_FAILED;
85     }
86 
87     const ErspanHdr *ehdr = (const ErspanHdr *)pkt;
88     uint16_t version = SCNtohs(ehdr->ver_vlan) >> 12;
89     uint16_t vlan_id = SCNtohs(ehdr->ver_vlan) & 0x0fff;
90 
91     SCLogDebug("ERSPAN: version %u vlan %u", version, vlan_id);
92 
93     /* only v1 is tested at this time */
94     if (version != 1) {
95         ENGINE_SET_EVENT(p,ERSPAN_UNSUPPORTED_VERSION);
96         return TM_ECODE_FAILED;
97     }
98 
99     if (vlan_id > 0) {
100         if (p->vlan_idx >= 2) {
101             ENGINE_SET_EVENT(p,ERSPAN_TOO_MANY_VLAN_LAYERS);
102             return TM_ECODE_FAILED;
103         }
104         p->vlan_id[p->vlan_idx] = vlan_id;
105         p->vlan_idx++;
106     }
107 
108     return DecodeEthernet(tv, dtv, p, pkt + sizeof(ErspanHdr), len - sizeof(ErspanHdr));
109 }
110 
111 /**
112  * @}
113  */
114