mirror of
https://github.com/zeek/zeek.git
synced 2025-10-10 02:28:21 +00:00
171 lines
5.1 KiB
JavaScript
171 lines
5.1 KiB
JavaScript
# Code written by Bernhard Ager (2007).
|
|
|
|
analyzer NetFlow withcontext {
|
|
analyzer: NetFlow_Analyzer;
|
|
flow: NetFlow_Flow;
|
|
}
|
|
|
|
analyzer NetFlow_Analyzer {
|
|
downflow = NetFlow_Flow;
|
|
upflow = NetFlow_Flow;
|
|
};
|
|
|
|
flow NetFlow_Flow {
|
|
datagram = NetFlowPacket withcontext(connection, this);
|
|
|
|
%member{
|
|
RecordType* nf_v5_header_type;
|
|
RecordType* nf_v5_record_type;
|
|
RecordType* nfheader_id_type;
|
|
char* identifier;
|
|
uint32 exporter_ip;
|
|
uint32 uptime;
|
|
double export_time;
|
|
bro_uint_t pdu_id;
|
|
%}
|
|
|
|
%init{
|
|
nf_v5_header_type =
|
|
internal_type("nf_v5_header")->AsRecordType();
|
|
nf_v5_record_type =
|
|
internal_type("nf_v5_record")->AsRecordType();
|
|
nfheader_id_type =
|
|
internal_type("nfheader_id")->AsRecordType();
|
|
pdu_id = 0;
|
|
identifier = NULL;
|
|
%}
|
|
|
|
# %cleanup does not only put the cleanup code into the destructor,
|
|
# but also at the end of the catch clause in NewData(). This is
|
|
# different from the documentation at
|
|
# http://www.bro-ids.org/wiki/index.php/BinPAC_Userguide#.25cleanup.7B....25.7D
|
|
#
|
|
# Unfortunately this means that we cannot clean up the identifier
|
|
# string. Note that IOSource destructors seemingly are never
|
|
# called anyway.
|
|
#
|
|
# %cleanup{
|
|
# delete[] identifier;
|
|
# %}
|
|
|
|
function set_exporter_ip(exporter_ip: uint32): bool
|
|
%{
|
|
this->exporter_ip = exporter_ip;
|
|
return true;
|
|
%}
|
|
|
|
function set_identifier(idf: const_charptr): bool
|
|
%{
|
|
if ( identifier )
|
|
delete[] identifier;
|
|
identifier = new char[strlen(idf) + 1];
|
|
strcpy(identifier, idf);
|
|
return true;
|
|
%}
|
|
|
|
function deliver_v5_header(count: uint16, sysuptime: uint32,
|
|
unix_secs: uint32, unix_nsecs: uint32,
|
|
flow_seq: uint32, eng_type: uint8,
|
|
eng_id: uint8, sample_int: uint16): bool
|
|
%{
|
|
uptime = sysuptime;
|
|
export_time = unix_secs + unix_nsecs / 1e9;
|
|
++pdu_id;
|
|
|
|
if ( ! ::netflow_v5_header )
|
|
return false;
|
|
|
|
RecordVal* nfheader = new RecordVal(nfheader_id_type);
|
|
nfheader->Assign(0, new StringVal(identifier));
|
|
nfheader->Assign(1, new Val(pdu_id, TYPE_COUNT));
|
|
|
|
RecordVal* v5header = new RecordVal(nf_v5_header_type);
|
|
v5header->Assign(0, nfheader);
|
|
v5header->Assign(1, new Val(count, TYPE_COUNT));
|
|
v5header->Assign(2, new IntervalVal(sysuptime, Milliseconds));
|
|
v5header->Assign(3, new Val(export_time, TYPE_TIME));
|
|
v5header->Assign(4, new Val(flow_seq, TYPE_COUNT));
|
|
v5header->Assign(5, new Val(eng_type, TYPE_COUNT));
|
|
v5header->Assign(6, new Val(eng_id, TYPE_COUNT));
|
|
v5header->Assign(7, new Val(sample_int, TYPE_COUNT));
|
|
v5header->Assign(8, new AddrVal(exporter_ip));
|
|
|
|
val_list* vl = new val_list;
|
|
vl->append(v5header);
|
|
mgr.QueueEvent(netflow_v5_header, vl);
|
|
|
|
return true;
|
|
%}
|
|
|
|
function deliver_v5_record(srcaddr: uint32, dstaddr: uint32,
|
|
nexthop: uint32, input: uint16, output: uint16,
|
|
dPkts: uint32, dOctets: uint32,
|
|
first: uint32, last: uint32,
|
|
srcport: uint16, dstport: uint16,
|
|
tcp_flags: uint8, prot: uint8, tos: uint8,
|
|
src_as: uint16, dst_as: uint16,
|
|
src_mask: uint8, dst_mask: uint8): bool
|
|
%{
|
|
if ( ! ::netflow_v5_record )
|
|
return false;
|
|
|
|
TransportProto proto = TRANSPORT_UNKNOWN;
|
|
switch ( prot ) {
|
|
case 1: proto = TRANSPORT_ICMP; break;
|
|
case 6: proto = TRANSPORT_TCP; break;
|
|
case 17: proto = TRANSPORT_UDP; break;
|
|
}
|
|
|
|
RecordVal* connid = new RecordVal(conn_id);
|
|
connid->Assign(0, new AddrVal(htonl(srcaddr)));
|
|
connid->Assign(1, new PortVal(srcport, proto));
|
|
connid->Assign(2, new AddrVal(htonl(dstaddr)));
|
|
connid->Assign(3, new PortVal(dstport, proto));
|
|
|
|
RecordVal* nfheader = new RecordVal(nfheader_id_type);
|
|
nfheader->Assign(0, new StringVal(identifier));
|
|
nfheader->Assign(1, new Val(pdu_id, TYPE_COUNT));
|
|
|
|
RecordVal* v5record = new RecordVal(nf_v5_record_type);
|
|
v5record->Assign(0, nfheader);
|
|
v5record->Assign(1, connid);
|
|
v5record->Assign(2, new AddrVal(htonl(nexthop)));
|
|
v5record->Assign(3, new Val(input, TYPE_COUNT));
|
|
v5record->Assign(4, new Val(output, TYPE_COUNT));
|
|
v5record->Assign(5, new Val(dPkts, TYPE_COUNT));
|
|
v5record->Assign(6, new Val(dOctets, TYPE_COUNT));
|
|
|
|
// Overflows are handled correctly by using 32 bit
|
|
// unsigned integer arithmetic.
|
|
double c_first = export_time - (uptime - first) * Milliseconds;
|
|
double c_last = export_time - (uptime - last) * Milliseconds;
|
|
v5record->Assign(7, new Val(c_first, TYPE_TIME));
|
|
v5record->Assign(8, new Val(c_last, TYPE_TIME));
|
|
|
|
v5record->Assign(9,
|
|
new Val((tcp_flags & TH_FIN) != 0, TYPE_BOOL));
|
|
v5record->Assign(10,
|
|
new Val((tcp_flags & TH_SYN) != 0, TYPE_BOOL));
|
|
v5record->Assign(11,
|
|
new Val((tcp_flags & TH_RST) != 0, TYPE_BOOL));
|
|
v5record->Assign(12,
|
|
new Val((tcp_flags & TH_PUSH) != 0, TYPE_BOOL));
|
|
v5record->Assign(13,
|
|
new Val((tcp_flags & TH_ACK) != 0, TYPE_BOOL));
|
|
v5record->Assign(14,
|
|
new Val((tcp_flags & TH_URG) != 0, TYPE_BOOL));
|
|
|
|
v5record->Assign(15, new Val(prot, TYPE_COUNT));
|
|
v5record->Assign(16, new Val(tos, TYPE_COUNT));
|
|
v5record->Assign(17, new Val(src_as, TYPE_COUNT));
|
|
v5record->Assign(18, new Val(dst_as, TYPE_COUNT));
|
|
v5record->Assign(19, new Val(src_mask, TYPE_COUNT));
|
|
v5record->Assign(20, new Val(dst_mask, TYPE_COUNT));
|
|
|
|
val_list* vl = new val_list;
|
|
vl->append(v5record);
|
|
mgr.QueueEvent(netflow_v5_record, vl);
|
|
|
|
return true;
|
|
%}
|
|
};
|