Rename analyzer/protocols -> analyzer/protocol

This commit is contained in:
Robin Sommer 2013-04-19 15:50:57 -07:00
parent f7a10d915b
commit 4bc2ba60c9
279 changed files with 114 additions and 116 deletions

View file

@ -0,0 +1,9 @@
include(BroPlugin)
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
bro_plugin_begin(UDP)
bro_plugin_cc(UDP.cc Plugin.cc)
bro_plugin_bif(events.bif)
bro_plugin_end()

View file

@ -0,0 +1,10 @@
#include "plugin/Plugin.h"
#include "analyzer/protocol/udp/UDP.h"
BRO_PLUGIN_BEGIN(UDP)
BRO_PLUGIN_DESCRIPTION("UDP Analyzer");
BRO_PLUGIN_ANALYZER("UDP", udp::UDP_Analyzer);
BRO_PLUGIN_BIF_FILE(events);
BRO_PLUGIN_END

View file

@ -0,0 +1,234 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include <algorithm>
#include "config.h"
#include "Net.h"
#include "NetVar.h"
#include "analyzer/protocol/udp/UDP.h"
#include "Reporter.h"
#include "Conn.h"
#include "events.bif.h"
using namespace analyzer::udp;
UDP_Analyzer::UDP_Analyzer(Connection* conn)
: TransportLayerAnalyzer("UDP", conn)
{
conn->EnableStatusUpdateTimer();
conn->SetInactivityTimeout(udp_inactivity_timeout);
request_len = reply_len = -1; // -1 means "haven't seen any activity"
}
UDP_Analyzer::~UDP_Analyzer()
{
// XXX: need to implement this!
// delete src_pkt_writer;
}
void UDP_Analyzer::Init()
{
}
void UDP_Analyzer::Done()
{
Analyzer::Done();
}
void UDP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
int seq, const IP_Hdr* ip, int caplen)
{
assert(ip);
Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen);
const struct udphdr* up = (const struct udphdr*) data;
// Increment data before checksum check so that data will
// point to UDP payload even if checksum fails. Particularly,
// it allows event packet_contents to get to the data.
data += sizeof(struct udphdr);
// We need the min() here because Ethernet frame padding can lead to
// caplen > len.
if ( packet_contents )
PacketContents(data, min(len, caplen) - sizeof(struct udphdr));
int chksum = up->uh_sum;
if ( ! ignore_checksums && caplen >= len )
{
bool bad = false;
if ( ip->IP4_Hdr() )
{
if ( chksum && ! ValidateChecksum(ip, up, len) )
bad = true;
}
/* checksum is not optional for IPv6 */
else if ( ! ValidateChecksum(ip, up, len) )
bad = true;
if ( bad )
{
Weird("bad_UDP_checksum");
if ( is_orig )
Conn()->CheckHistory(HIST_ORIG_CORRUPT_PKT, 'C');
else
Conn()->CheckHistory(HIST_RESP_CORRUPT_PKT, 'c');
return;
}
}
int ulen = ntohs(up->uh_ulen);
if ( ulen != len )
Weird(fmt("UDP_datagram_length_mismatch(%d!=%d)", ulen, len));
len -= sizeof(struct udphdr);
ulen -= sizeof(struct udphdr);
caplen -= sizeof(struct udphdr);
Conn()->SetLastTime(current_timestamp);
if ( udp_contents )
{
PortVal port_val(ntohs(up->uh_dport), TRANSPORT_UDP);
Val* result = 0;
bool do_udp_contents = false;
if ( is_orig )
{
result = udp_content_delivery_ports_orig->Lookup(
&port_val);
if ( udp_content_deliver_all_orig ||
(result && result->AsBool()) )
do_udp_contents = true;
}
else
{
result = udp_content_delivery_ports_resp->Lookup(
&port_val);
if ( udp_content_deliver_all_resp ||
(result && result->AsBool()) )
do_udp_contents = true;
}
if ( do_udp_contents )
{
val_list* vl = new val_list;
vl->append(BuildConnVal());
vl->append(new Val(is_orig, TYPE_BOOL));
vl->append(new StringVal(len, (const char*) data));
ConnectionEvent(udp_contents, vl);
}
}
if ( is_orig )
{
Conn()->CheckHistory(HIST_ORIG_DATA_PKT, 'D');
if ( request_len < 0 )
request_len = ulen;
else
{
request_len += ulen;
#ifdef DEBUG
if ( request_len < 0 )
reporter->Warning("wrapping around for UDP request length");
#endif
}
Event(udp_request);
}
else
{
Conn()->CheckHistory(HIST_RESP_DATA_PKT, 'd');
if ( reply_len < 0 )
reply_len = ulen;
else
{
reply_len += ulen;
#ifdef DEBUG
if ( reply_len < 0 )
reporter->Warning("wrapping around for UDP reply length");
#endif
}
Event(udp_reply);
}
if ( caplen >= len )
ForwardPacket(len, data, is_orig, seq, ip, caplen);
}
void UDP_Analyzer::UpdateConnVal(RecordVal *conn_val)
{
int orig_endp_idx = connection_type->FieldOffset("orig");
int resp_endp_idx = connection_type->FieldOffset("resp");
RecordVal *orig_endp = conn_val->Lookup(orig_endp_idx)->AsRecordVal();
RecordVal *resp_endp = conn_val->Lookup(resp_endp_idx)->AsRecordVal();
orig_endp = conn_val->Lookup(orig_endp_idx)->AsRecordVal();
resp_endp = conn_val->Lookup(resp_endp_idx)->AsRecordVal();
UpdateEndpointVal(orig_endp, 1);
UpdateEndpointVal(resp_endp, 0);
// Call children's UpdateConnVal
Analyzer::UpdateConnVal(conn_val);
}
void UDP_Analyzer::UpdateEndpointVal(RecordVal* endp, int is_orig)
{
bro_int_t size = is_orig ? request_len : reply_len;
if ( size < 0 )
{
endp->Assign(0, new Val(0, TYPE_COUNT));
endp->Assign(1, new Val(int(UDP_INACTIVE), TYPE_COUNT));
}
else
{
endp->Assign(0, new Val(size, TYPE_COUNT));
endp->Assign(1, new Val(int(UDP_ACTIVE), TYPE_COUNT));
}
}
bool UDP_Analyzer::IsReuse(double /* t */, const u_char* /* pkt */)
{
return 0;
}
unsigned int UDP_Analyzer::MemoryAllocation() const
{
// A rather low lower bound....
return Analyzer::MemoryAllocation() + padded_sizeof(*this) - 24;
}
bool UDP_Analyzer::ValidateChecksum(const IP_Hdr* ip, const udphdr* up, int len)
{
uint32 sum;
if ( len % 2 == 1 )
// Add in pad byte.
sum = htons(((const u_char*) up)[len - 1] << 8);
else
sum = 0;
sum = ones_complement_checksum(ip->SrcAddr(), sum);
sum = ones_complement_checksum(ip->DstAddr(), sum);
// Note, for IPv6, strictly speaking the protocol and length fields are
// 32 bits rather than 16 bits. But because the upper bits are all zero,
// we get the same checksum either way.
sum += htons(IPPROTO_UDP);
sum += htons((unsigned short) len);
sum = ones_complement_checksum((void*) up, len, sum);
return sum == 0xffff;
}

View file

@ -0,0 +1,52 @@
// See the file "COPYING" in the main distribution directory for copyright.
#ifndef ANALYZER_PROTOCOL_UDP_UDP_H
#define ANALYZER_PROTOCOL_UDP_UDP_H
#include "analyzer/Analyzer.h"
#include <netinet/udp.h>
namespace analyzer { namespace udp {
typedef enum {
UDP_INACTIVE, // no packet seen
UDP_ACTIVE, // packets seen
} UDP_EndpointState;
class UDP_Analyzer : public analyzer::TransportLayerAnalyzer {
public:
UDP_Analyzer(Connection* conn);
virtual ~UDP_Analyzer();
virtual void Init();
virtual void UpdateConnVal(RecordVal *conn_val);
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn)
{ return new UDP_Analyzer(conn); }
protected:
virtual void Done();
virtual void DeliverPacket(int len, const u_char* data, bool orig,
int seq, const IP_Hdr* ip, int caplen);
virtual bool IsReuse(double t, const u_char* pkt);
virtual unsigned int MemoryAllocation() const;
// Returns true if the checksum is valid, false if not
static bool ValidateChecksum(const IP_Hdr* ip, const struct udphdr* up,
int len);
bro_int_t request_len, reply_len;
private:
void UpdateEndpointVal(RecordVal* endp, int is_orig);
#define HIST_ORIG_DATA_PKT 0x1
#define HIST_RESP_DATA_PKT 0x2
#define HIST_ORIG_CORRUPT_PKT 0x4
#define HIST_RESP_CORRUPT_PKT 0x8
};
} } // namespace analyzer::*
#endif

View file

@ -0,0 +1,38 @@
## Generated for each packet sent by a UDP flow's originator. This a potentially
## expensive event due to the volume of UDP traffic and should be used with
## care.
##
## u: The connection record for the corresponding UDP flow.
##
## .. bro:see:: udp_contents udp_reply udp_session_done
event udp_request%(u: connection%);
## Generated for each packet sent by a UDP flow's responder. This a potentially
## expensive event due to the volume of UDP traffic and should be used with
## care.
##
## u: The connection record for the corresponding UDP flow.
##
## .. bro:see:: udp_contents udp_request udp_session_done
event udp_reply%(u: connection%);
## Generated for UDP packets to pass on their payload. As the number of UDP
## packets can be very large, this event is normally raised only for those on
## ports configured in :bro:id:`udp_content_delivery_ports_orig` (for packets
## sent by the flow's originator) or :bro:id:`udp_content_delivery_ports_resp`
## (for packets sent by the flow's responder). However, delivery can be enabled
## for all UDP request and reply packets by setting
## :bro:id:`udp_content_deliver_all_orig` or
## :bro:id:`udp_content_deliver_all_resp`, respectively. Note that this
## event is also raised for all matching UDP packets, including empty ones.
##
## u: The connection record for the corresponding UDP flow.
##
## is_orig: True if the event is raised for the originator side.
##
## contents: TODO.
##
## .. bro:see:: udp_reply udp_request udp_session_done
## udp_content_deliver_all_orig udp_content_deliver_all_resp
## udp_content_delivery_ports_orig udp_content_delivery_ports_resp
event udp_contents%(u: connection, is_orig: bool, contents: string%);