mirror of
https://github.com/zeek/zeek.git
synced 2025-10-14 04:28:20 +00:00
Merge branch 'master' into fastpath
This commit is contained in:
commit
4c278ce387
57 changed files with 716 additions and 4 deletions
10
src/AYIYA.cc
10
src/AYIYA.cc
|
@ -20,5 +20,13 @@ void AYIYA_Analyzer::Done()
|
|||
void AYIYA_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
|
||||
interp->NewData(orig, data, data + len);
|
||||
|
||||
try
|
||||
{
|
||||
interp->NewData(orig, data, data + len);
|
||||
}
|
||||
catch ( const binpac::Exception& e )
|
||||
{
|
||||
ProtocolViolation(fmt("Binpac exception: %s", e.c_msg()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "Syslog-binpac.h"
|
||||
#include "Teredo.h"
|
||||
#include "ConnSizeAnalyzer.h"
|
||||
#include "GTPv1.h"
|
||||
|
||||
// Keep same order here as in AnalyzerTag definition!
|
||||
const Analyzer::Config Analyzer::analyzer_configs[] = {
|
||||
|
@ -143,6 +144,9 @@ const Analyzer::Config Analyzer::analyzer_configs[] = {
|
|||
{ AnalyzerTag::Teredo, "TEREDO",
|
||||
Teredo_Analyzer::InstantiateAnalyzer,
|
||||
Teredo_Analyzer::Available, 0, false },
|
||||
{ AnalyzerTag::GTPv1, "GTPV1",
|
||||
GTPv1_Analyzer::InstantiateAnalyzer,
|
||||
GTPv1_Analyzer::Available, 0, false },
|
||||
|
||||
{ AnalyzerTag::File, "FILE", File_Analyzer::InstantiateAnalyzer,
|
||||
File_Analyzer::Available, 0, false },
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace AnalyzerTag {
|
|||
AYIYA,
|
||||
SOCKS,
|
||||
Teredo,
|
||||
GTPv1,
|
||||
|
||||
// Other
|
||||
File, Backdoor, InterConn, SteppingStone, TCPStats,
|
||||
|
|
|
@ -203,6 +203,8 @@ binpac_target(dns.pac
|
|||
dns-protocol.pac dns-analyzer.pac)
|
||||
binpac_target(dns_tcp.pac
|
||||
dns.pac)
|
||||
binpac_target(gtpv1.pac
|
||||
gtpv1-protocol.pac gtpv1-analyzer.pac)
|
||||
binpac_target(http.pac
|
||||
http-protocol.pac http-analyzer.pac)
|
||||
binpac_target(ncp.pac)
|
||||
|
@ -332,6 +334,7 @@ set(bro_SRCS
|
|||
Frame.cc
|
||||
Func.cc
|
||||
Gnutella.cc
|
||||
GTPv1.cc
|
||||
HTTP.cc
|
||||
HTTP-binpac.cc
|
||||
Hash.cc
|
||||
|
|
31
src/GTPv1.cc
Normal file
31
src/GTPv1.cc
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include "GTPv1.h"
|
||||
|
||||
GTPv1_Analyzer::GTPv1_Analyzer(Connection* conn)
|
||||
: Analyzer(AnalyzerTag::GTPv1, conn)
|
||||
{
|
||||
interp = new binpac::GTPv1::GTPv1_Conn(this);
|
||||
}
|
||||
|
||||
GTPv1_Analyzer::~GTPv1_Analyzer()
|
||||
{
|
||||
delete interp;
|
||||
}
|
||||
|
||||
void GTPv1_Analyzer::Done()
|
||||
{
|
||||
Analyzer::Done();
|
||||
Event(udp_session_done);
|
||||
}
|
||||
|
||||
void GTPv1_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
|
||||
try
|
||||
{
|
||||
interp->NewData(orig, data, data + len);
|
||||
}
|
||||
catch ( const binpac::Exception& e )
|
||||
{
|
||||
ProtocolViolation(fmt("Binpac exception: %s", e.c_msg()));
|
||||
}
|
||||
}
|
29
src/GTPv1.h
Normal file
29
src/GTPv1.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef GTPv1_h
|
||||
#define GTPv1_h
|
||||
|
||||
#include "gtpv1_pac.h"
|
||||
|
||||
class GTPv1_Analyzer : public Analyzer {
|
||||
public:
|
||||
GTPv1_Analyzer(Connection* conn);
|
||||
virtual ~GTPv1_Analyzer();
|
||||
|
||||
virtual void Done();
|
||||
virtual void DeliverPacket(int len, const u_char* data, bool orig,
|
||||
int seq, const IP_Hdr* ip, int caplen);
|
||||
|
||||
static Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
{ return new GTPv1_Analyzer(conn); }
|
||||
|
||||
static bool Available()
|
||||
{ return BifConst::Tunnel::enable_gtpv1 &&
|
||||
BifConst::Tunnel::max_depth > 0; }
|
||||
|
||||
protected:
|
||||
friend class AnalyzerTimer;
|
||||
void ExpireTimer(double t);
|
||||
|
||||
binpac::GTPv1::GTPv1_Conn* interp;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -5,6 +5,7 @@
|
|||
#include "Var.h"
|
||||
#include "NetVar.h"
|
||||
|
||||
RecordType* gtpv1_hdr_type;
|
||||
RecordType* conn_id;
|
||||
RecordType* endpoint;
|
||||
RecordType* endpoint_stats;
|
||||
|
@ -308,6 +309,7 @@ void init_net_var()
|
|||
#include "input.bif.netvar_init"
|
||||
#include "reporter.bif.netvar_init"
|
||||
|
||||
gtpv1_hdr_type = internal_type("gtpv1_hdr")->AsRecordType();
|
||||
conn_id = internal_type("conn_id")->AsRecordType();
|
||||
endpoint = internal_type("endpoint")->AsRecordType();
|
||||
endpoint_stats = internal_type("endpoint_stats")->AsRecordType();
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "EventRegistry.h"
|
||||
#include "Stats.h"
|
||||
|
||||
extern RecordType* gtpv1_hdr_type;
|
||||
extern RecordType* conn_id;
|
||||
extern RecordType* endpoint;
|
||||
extern RecordType* endpoint_stats;
|
||||
|
|
|
@ -15,8 +15,10 @@ const Tunnel::max_depth: count;
|
|||
const Tunnel::enable_ip: bool;
|
||||
const Tunnel::enable_ayiya: bool;
|
||||
const Tunnel::enable_teredo: bool;
|
||||
const Tunnel::enable_gtpv1: bool;
|
||||
const Tunnel::yielding_teredo_decapsulation: bool;
|
||||
const Tunnel::delay_teredo_confirmation: bool;
|
||||
const Tunnel::delay_gtp_confirmation: bool;
|
||||
const Tunnel::ip_tunnel_timeout: interval;
|
||||
|
||||
const Threading::heartbeat_interval: interval;
|
||||
|
|
|
@ -577,6 +577,19 @@ event teredo_origin_indication%(outer: connection, inner: teredo_hdr%);
|
|||
## it may become particularly expensive for real-time analysis.
|
||||
event teredo_bubble%(outer: connection, inner: teredo_hdr%);
|
||||
|
||||
## Generated for GTPv1 G-PDU packets. That is, packets with a UDP payload
|
||||
## that includes a GTP header followed by an IPv4 or IPv6 packet.
|
||||
##
|
||||
## outer: The GTP outer tunnel connection.
|
||||
##
|
||||
## inner_gtp: The GTP header.
|
||||
##
|
||||
## inner_ip: The inner IP and transport layer packet headers.
|
||||
##
|
||||
## .. note:: Since this event may be raised on a per-packet basis, handling
|
||||
## it may become particularly expensive for real-time analysis.
|
||||
event gtpv1_g_pdu_packet%(outer: connection, inner_gtp: gtpv1_hdr, inner_ip: pkt_hdr%);
|
||||
|
||||
## Generated for every packet that has a non-empty transport-layer payload.
|
||||
## This is a very low-level and expensive event that should be avoided when
|
||||
## at all possible. It's usually infeasible to handle when processing even
|
||||
|
@ -858,7 +871,7 @@ event udp_contents%(u: connection, is_orig: bool, contents: string%);
|
|||
## Generated when a UDP session for a supported protocol has finished. Some of
|
||||
## Bro's application-layer UDP analyzers flag the end of a session by raising
|
||||
## this event. Currently, the analyzers for DNS, NTP, Netbios, Syslog, AYIYA,
|
||||
## and Teredo support this.
|
||||
## Teredo, and GTPv1 support this.
|
||||
##
|
||||
## u: The connection record for the corresponding UDP flow.
|
||||
##
|
||||
|
|
161
src/gtpv1-analyzer.pac
Normal file
161
src/gtpv1-analyzer.pac
Normal file
|
@ -0,0 +1,161 @@
|
|||
|
||||
connection GTPv1_Conn(bro_analyzer: BroAnalyzer)
|
||||
{
|
||||
upflow = GTPv1_Flow(true);
|
||||
downflow = GTPv1_Flow(false);
|
||||
|
||||
%member{
|
||||
bool valid_orig;
|
||||
bool valid_resp;
|
||||
%}
|
||||
|
||||
%init{
|
||||
valid_orig = valid_resp = false;
|
||||
%}
|
||||
|
||||
function valid(orig: bool): bool
|
||||
%{
|
||||
return orig ? valid_orig : valid_resp;
|
||||
%}
|
||||
|
||||
function set_valid(orig: bool, val: bool): void
|
||||
%{
|
||||
if ( orig )
|
||||
valid_orig = val;
|
||||
else
|
||||
valid_resp = val;
|
||||
%}
|
||||
}
|
||||
|
||||
%code{
|
||||
inline void violate(const char* r, const BroAnalyzer& a, const bytestring& p)
|
||||
{
|
||||
a->ProtocolViolation(r, (const char*) p.data(), p.length());
|
||||
}
|
||||
%}
|
||||
|
||||
flow GTPv1_Flow(is_orig: bool)
|
||||
{
|
||||
datagram = GTPv1_Header withcontext(connection, this);
|
||||
|
||||
function process_gtpv1(pdu: GTPv1_Header): bool
|
||||
%{
|
||||
BroAnalyzer a = connection()->bro_analyzer();
|
||||
Connection *c = a->Conn();
|
||||
const EncapsulationStack* e = c->GetEncapsulation();
|
||||
|
||||
connection()->set_valid(is_orig(), false);
|
||||
|
||||
if ( e && e->Depth() >= BifConst::Tunnel::max_depth )
|
||||
{
|
||||
reporter->Weird(c, "tunnel_depth");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( e && e->LastType() == BifEnum::Tunnel::GTPv1 )
|
||||
{
|
||||
// GTP is never tunneled in GTP so, this must be a regular packet
|
||||
violate("GTP-in-GTP", a, ${pdu.packet});
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ${pdu.version} != 1 )
|
||||
{
|
||||
// Only know of GTPv1 with Version == 1
|
||||
violate("GTPv1 bad Version", a, ${pdu.packet});
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! ${pdu.pt_flag} )
|
||||
{
|
||||
// Not interested in GTP'
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ${pdu.e_flag} )
|
||||
{
|
||||
// TODO: can't currently parse past extension headers
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ${pdu.msg_type} != 0xff )
|
||||
{
|
||||
// Only interested in decapsulating user plane data beyond here.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ${pdu.packet}.length() < (int)sizeof(struct ip) )
|
||||
{
|
||||
violate("Truncated GTPv1", a, ${pdu.packet});
|
||||
return false;
|
||||
}
|
||||
|
||||
const struct ip* ip = (const struct ip*) ${pdu.packet}.data();
|
||||
|
||||
if ( ip->ip_v != 4 && ip->ip_v != 6 )
|
||||
{
|
||||
violate("non-IP packet in GTPv1", a, ${pdu.packet});
|
||||
return false;
|
||||
}
|
||||
|
||||
IP_Hdr* inner = 0;
|
||||
int result = sessions->ParseIPPacket(${pdu.packet}.length(),
|
||||
${pdu.packet}.data(), ip->ip_v == 6 ? IPPROTO_IPV6 : IPPROTO_IPV4,
|
||||
inner);
|
||||
|
||||
if ( result == 0 )
|
||||
{
|
||||
connection()->set_valid(is_orig(), true);
|
||||
|
||||
if ( (! BifConst::Tunnel::delay_gtp_confirmation) ||
|
||||
(connection()->valid(true) && connection()->valid(false)) )
|
||||
a->ProtocolConfirmation();
|
||||
}
|
||||
|
||||
else if ( result < 0 )
|
||||
violate("Truncated GTPv1", a, ${pdu.packet});
|
||||
|
||||
else
|
||||
violate("GTPv1 payload length", a, ${pdu.packet});
|
||||
|
||||
if ( result != 0 )
|
||||
{
|
||||
delete inner;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ::gtpv1_g_pdu_packet )
|
||||
{
|
||||
RecordVal* rv = new RecordVal(gtpv1_hdr_type);
|
||||
|
||||
rv->Assign(0, new Val(${pdu.version}, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(${pdu.pt_flag}, TYPE_BOOL));
|
||||
rv->Assign(2, new Val(${pdu.rsv}, TYPE_BOOL));
|
||||
rv->Assign(3, new Val(${pdu.e_flag}, TYPE_BOOL));
|
||||
rv->Assign(4, new Val(${pdu.s_flag}, TYPE_BOOL));
|
||||
rv->Assign(5, new Val(${pdu.pn_flag}, TYPE_BOOL));
|
||||
rv->Assign(6, new Val(${pdu.msg_type}, TYPE_COUNT));
|
||||
rv->Assign(7, new Val(ntohs(${pdu.length}), TYPE_COUNT));
|
||||
rv->Assign(8, new Val(ntohl(${pdu.teid}), TYPE_COUNT));
|
||||
|
||||
if ( ${pdu.has_opt} )
|
||||
{
|
||||
rv->Assign(9, new Val(ntohs(${pdu.opt_hdr.seq}), TYPE_COUNT));
|
||||
rv->Assign(10, new Val(${pdu.opt_hdr.n_pdu}, TYPE_COUNT));
|
||||
rv->Assign(11, new Val(${pdu.opt_hdr.next_type}, TYPE_COUNT));
|
||||
}
|
||||
|
||||
BifEvent::generate_gtpv1_g_pdu_packet(a, c, rv,
|
||||
inner->BuildPktHdrVal());
|
||||
}
|
||||
|
||||
EncapsulatingConn ec(c, BifEnum::Tunnel::GTPv1);
|
||||
|
||||
sessions->DoNextInnerPacket(network_time(), 0, inner, e, ec);
|
||||
|
||||
return (result == 0) ? true : false;
|
||||
%}
|
||||
|
||||
};
|
||||
|
||||
refine typeattr GTPv1_Header += &let { proc_gtpv1 = $context.flow.process_gtpv1(this); };
|
27
src/gtpv1-protocol.pac
Normal file
27
src/gtpv1-protocol.pac
Normal file
|
@ -0,0 +1,27 @@
|
|||
|
||||
type GTPv1_Header = record {
|
||||
flags: uint8;
|
||||
msg_type: uint8;
|
||||
length: uint16;
|
||||
teid: uint32;
|
||||
opt: case has_opt of {
|
||||
true -> opt_hdr: GTPv1_Opt_Header;
|
||||
false -> no_opt: empty;
|
||||
} &requires(has_opt);
|
||||
packet: bytestring &restofdata;
|
||||
|
||||
} &let {
|
||||
version: uint8 = (flags & 0xE0) >> 5;
|
||||
pt_flag: bool = flags & 0x10;
|
||||
rsv: bool = flags & 0x08;
|
||||
e_flag: bool = flags & 0x04;
|
||||
s_flag: bool = flags & 0x02;
|
||||
pn_flag: bool = flags & 0x01;
|
||||
has_opt: bool = flags & 0x07;
|
||||
} &byteorder = littleendian;
|
||||
|
||||
type GTPv1_Opt_Header = record {
|
||||
seq: uint16;
|
||||
n_pdu: uint8;
|
||||
next_type: uint8;
|
||||
}
|
10
src/gtpv1.pac
Normal file
10
src/gtpv1.pac
Normal file
|
@ -0,0 +1,10 @@
|
|||
%include binpac.pac
|
||||
%include bro.pac
|
||||
|
||||
analyzer GTPv1 withcontext {
|
||||
connection: GTPv1_Conn;
|
||||
flow: GTPv1_Flow;
|
||||
};
|
||||
|
||||
%include gtpv1-protocol.pac
|
||||
%include gtpv1-analyzer.pac
|
|
@ -184,6 +184,7 @@ enum Type %{
|
|||
AYIYA,
|
||||
TEREDO,
|
||||
SOCKS,
|
||||
GTPv1,
|
||||
%}
|
||||
|
||||
type EncapsulatingConn: record;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue