1 //--------------------------------------------------------------------------
2 // Copyright (C) 2020-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation.  You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 //--------------------------------------------------------------------------
18 // cd_vxlan.cc author Bhagya Tholpady <bbantwal@cisco.com>
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include "framework/codec.h"
25 #include "log/text_log.h"
26 #include "main/snort_config.h"
27 #include "packet_io/active.h"
28 
29 using namespace snort;
30 
31 #define CD_VXLAN_NAME "vxlan"
32 #define CD_VXLAN_HELP "support for Virtual Extensible LAN"
33 
34 namespace
35 {
36 class VxlanCodec : public Codec
37 {
38 public:
VxlanCodec()39     VxlanCodec() : Codec(CD_VXLAN_NAME) { }
40 
41     void get_protocol_ids(std::vector<ProtocolId>& v) override;
42     bool decode(const RawData&, CodecData&, DecodeData&) override;
43     void log(TextLog* const, const uint8_t* pkt, const uint16_t len) override;
44 };
45 
46 struct VXLANHdr
47 {
48     uint8_t flags;
49     uint8_t reserved_1[3];
50     uint8_t vni[3]; //VXLAN network id
51     uint8_t reserved_2;
52 };
53 constexpr uint16_t VXLAN_MIN_HDR_LEN = 8;
54 } // anonymous namespace
55 
get_protocol_ids(std::vector<ProtocolId> & v)56 void VxlanCodec::get_protocol_ids(std::vector<ProtocolId>& v)
57 {
58     v.push_back(ProtocolId::VXLAN);
59 }
60 
decode(const RawData & raw,CodecData & codec,DecodeData &)61 bool VxlanCodec::decode(const RawData& raw, CodecData& codec, DecodeData&)
62 {
63     if ( raw.len < VXLAN_MIN_HDR_LEN )
64         return false;
65 
66     const VXLANHdr* const hdr = reinterpret_cast<const VXLANHdr*>(raw.data);
67 
68     if ( hdr->flags != 0x08 )
69         return false;
70 
71     if ( codec.conf->tunnel_bypass_enabled(TUNNEL_VXLAN) )
72         codec.tunnel_bypass = true;
73 
74     codec.lyr_len = VXLAN_MIN_HDR_LEN;
75     codec.proto_bits |= PROTO_BIT__VXLAN;
76     codec.next_prot_id = ProtocolId::ETHERNET_802_3;
77     codec.codec_flags |= CODEC_NON_IP_TUNNEL;
78 
79     return true;
80 }
81 
log(TextLog * const text_log,const uint8_t * raw_pkt,const uint16_t)82 void VxlanCodec::log(TextLog* const text_log, const uint8_t* raw_pkt,
83     const uint16_t /*lyr_len*/)
84 {
85     const VXLANHdr* const hdr = reinterpret_cast<const VXLANHdr*>(raw_pkt);
86     uint32_t vni = ( hdr->vni[0] << 16 ) | ( hdr->vni[1] << 8 ) | hdr->vni[2];
87     TextLog_Print(text_log, "network identifier: %u", vni);
88 }
89 
90 //-------------------------------------------------------------------------
91 // api
92 //-------------------------------------------------------------------------
93 
ctor(Module *)94 static Codec* ctor(Module*)
95 { return new VxlanCodec(); }
96 
dtor(Codec * cd)97 static void dtor(Codec* cd)
98 { delete cd; }
99 
100 static const CodecApi vxlan_api =
101 {
102     {
103         PT_CODEC,
104         sizeof(CodecApi),
105         CDAPI_VERSION,
106         0,
107         API_RESERVED,
108         API_OPTIONS,
109         CD_VXLAN_NAME,
110         CD_VXLAN_HELP,
111         nullptr,
112         nullptr
113     },
114     nullptr, // pinit
115     nullptr, // pterm
116     nullptr, // tinit
117     nullptr, // tterm
118     ctor, // ctor
119     dtor, // dtor
120 };
121 
122 #ifdef BUILDING_SO
123 SO_PUBLIC const BaseApi* snort_plugins[] =
124 #else
125 const BaseApi* cd_vxlan[] =
126 #endif
127 {
128     &vxlan_api.base,
129     nullptr
130 };
131 
132