mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Merge remote-tracking branch 'j-gras/llpoc'
* j-gras/llpoc: (43 commits) Update NEWS Fix build on FreeBSD, which was missing full definition of sockaddr for ARP Update hashes for external testing repos Fix handling of session analysis. Fix Sessions::DoNextPacket to ignore ARP packets and not report weirds for them Packet analysis cleanup. Minor cleanup Simplify packet analyzer config. Make default packet analyzer definition explicit. Add explicit root analyzer for packet analysis. Extend packet analysis test. Simplify MPLS analysis. Improve packet analysis data flow. Improve packet analyzer API. Rename DefaultAnalyzer to IP. Move ARP analysis into packet analyzer. Small cleanup of packet analysis. Fix some build issues from the rebase Remove encap_hdr_size (replaced by skip analyzer). Add skip analyzer test and update baselines. ...
This commit is contained in:
commit
68e20def1e
174 changed files with 3886 additions and 1046 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -4,7 +4,7 @@ tmp
|
|||
|
||||
# Configuration and build directories for CLion
|
||||
.idea
|
||||
cmake-build-debug
|
||||
cmake-build-*
|
||||
|
||||
# skip DS Store for MacOS
|
||||
.DS_Store
|
||||
|
|
110
CHANGES
110
CHANGES
|
@ -1,3 +1,113 @@
|
|||
3.3.0-dev.329 | 2020-09-23 11:32:06 -0700
|
||||
|
||||
* Update NEWS (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Fix build on FreeBSD, which was missing full definition of sockaddr for ARP (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Update hashes for external testing repos (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Fix handling of session analysis.
|
||||
|
||||
This reverts commit 0e51be18ac59d7a176f18780f1f8df85561449b9. (Jan Grashoefer)
|
||||
|
||||
* Fix Sessions::DoNextPacket to ignore ARP packets and not report weirds for them (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Packet analysis cleanup. (Jan Grashoefer)
|
||||
|
||||
* Minor cleanup (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Simplify packet analyzer config. (Jan Grashoefer)
|
||||
|
||||
* Make default packet analyzer definition explicit. (Jan Grashoefer)
|
||||
|
||||
* Add explicit root analyzer for packet analysis. (Jan Grashoefer)
|
||||
|
||||
* Extend packet analysis test. (Jan Grashoefer)
|
||||
|
||||
* Simplify MPLS analysis. (Jan Grashoefer)
|
||||
|
||||
* Improve packet analysis data flow. (Jan Grashoefer)
|
||||
|
||||
* Improve packet analyzer API. (Jan Grashoefer)
|
||||
|
||||
* Rename DefaultAnalyzer to IP. (Jan Grashoefer)
|
||||
|
||||
* Move ARP analysis into packet analyzer. (Jan Grashoefer)
|
||||
|
||||
* Small cleanup of packet analysis. (Jan Grashoefer)
|
||||
|
||||
* Fix some build issues from the rebase (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Remove encap_hdr_size (replaced by skip analyzer). (Jan Grashoefer)
|
||||
|
||||
* Add skip analyzer test and update baselines. (Jan Grashoefer)
|
||||
|
||||
* Allow to overwrite packet analysis mappings. (Jan Grashoefer)
|
||||
|
||||
* Add SkipAnalyzer.
|
||||
|
||||
This is WIP: The test case would require a new pcap or the possibility
|
||||
to overwrite analyzer mappings. The CustomEncapsulationSkip method and
|
||||
the corresponding options need to be removed. (Jan Grashoefer)
|
||||
|
||||
* Suggested code improvements for packet analysis. (Jan Grashoefer)
|
||||
|
||||
* Improve naming in packet analysis. (Jan Grashoefer)
|
||||
|
||||
* Migrate all packet analyzers to new API. (Jan Grashoefer)
|
||||
|
||||
* Remove magic identifiers from Ethernet analyzer. (Jan Grashoefer)
|
||||
|
||||
* Bring back default packet analysis.
|
||||
|
||||
Default analyzers can be configured per packet analyzer by omitting the
|
||||
identifier in the ConfigEntry. (Jan Grashoefer)
|
||||
|
||||
* Further simplified the packet analysis API.
|
||||
|
||||
This is still WIP and includes the following changes:
|
||||
* Dispatchers are now part of analyzers (moving dispatching logic from
|
||||
the manager to the analyzers)
|
||||
* All available analyzers are instantiated on start up
|
||||
* Removal of configuration class (Jan Grashoefer)
|
||||
|
||||
* Move dispatching into packet analyzers.
|
||||
|
||||
WIP that updates only the Ethernet analyzer. (Jan Grashoefer)
|
||||
|
||||
* Move cur_pos from packet into packet manager loop. (Jan Grashoefer)
|
||||
|
||||
* Remove packet_analysis/Defines.h
|
||||
|
||||
- Replace uses of identifier_t with uint32_t
|
||||
- Replace repeated usage of tuple type for Analysis results with type alias (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Move VectorDispatcher to be the only dispatcher (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Remove Manager::Reset() method (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Remove enabled state from Components, ability to enable/disable from Manager (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Use shared_ptr instead of raw pointers in packet_analysis for analyzers and dispatchers (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Whitespace fixes from review (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Reorganize some pointer handling (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Fix ordering of debug logger strings to match the enum (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Fixes for various btest issues
|
||||
|
||||
- Fix handling of truncated ethernet headers, fix core.truncation test output
|
||||
- Update commit hashes for external private test repo (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Merge ProtocolAnalyzerSet into Manager, remove AnalyzerSet base class (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Minor fixes for packet analyzer renaming. (Jan Grashoefer)
|
||||
|
||||
* Renamed LL-Analyzers to Packet Analyzers. (Jan Grashoefer)
|
||||
|
||||
* Initial implementation of Lower-Level analyzers (Peter Oettig)
|
||||
|
||||
3.3.0-dev.285 | 2020-09-22 16:01:51 -0700
|
||||
|
||||
|
|
5
NEWS
5
NEWS
|
@ -11,6 +11,11 @@ New Functionality
|
|||
|
||||
- Added support for EDNS0 Cookie and Keep-Alive options.
|
||||
|
||||
- Added new Packet Analysis plugin architecture for parsing packet headers
|
||||
at layers below the existing Session analysis plugins. This allows
|
||||
writing plugins to parse the various parts of a packet header separately,
|
||||
chaining down into other plugins as needed.
|
||||
|
||||
Changed Functionality
|
||||
---------------------
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
3.3.0-dev.285
|
||||
3.3.0-dev.329
|
||||
|
|
|
@ -1225,10 +1225,6 @@ const rpc_timeout = 24 sec &redef;
|
|||
## means "forever", which resists evasion, but can lead to state accrual.
|
||||
const frag_timeout = 0.0 sec &redef;
|
||||
|
||||
## If positive, indicates the encapsulation header size that should
|
||||
## be skipped. This applies to all packets.
|
||||
const encap_hdr_size = 0 &redef;
|
||||
|
||||
## Whether to use the ``ConnSize`` analyzer to count the number of packets and
|
||||
## IP-level bytes transferred by each endpoint. If true, these values are
|
||||
## returned in the connection's :zeek:see:`endpoint` record value.
|
||||
|
@ -5341,3 +5337,19 @@ event net_done(t: time)
|
|||
# execution would be another idea.
|
||||
@if ( __init_primary_bifs() )
|
||||
@endif
|
||||
|
||||
module PacketAnalyzer;
|
||||
|
||||
export {
|
||||
type DispatchEntry : record {
|
||||
## The analyzer to dispatch.
|
||||
analyzer : PacketAnalyzer::Tag;
|
||||
};
|
||||
|
||||
## A packet analyzer may extract a numeric identifier, which can be found in the
|
||||
## packet data and denotes the encapsulated protocol. A DispatchMap allows to map
|
||||
## the identifier to a child analyzer, which is defined using a DispatchEntry.
|
||||
type DispatchMap : table[count] of DispatchEntry;
|
||||
}
|
||||
|
||||
@load base/packet-protocols
|
||||
|
|
14
scripts/base/packet-protocols/__load__.zeek
Normal file
14
scripts/base/packet-protocols/__load__.zeek
Normal file
|
@ -0,0 +1,14 @@
|
|||
@load base/packet-protocols/root
|
||||
@load base/packet-protocols/ip
|
||||
@load base/packet-protocols/skip
|
||||
@load base/packet-protocols/ethernet
|
||||
@load base/packet-protocols/fddi
|
||||
@load base/packet-protocols/ieee802_11
|
||||
@load base/packet-protocols/ieee802_11_radio
|
||||
@load base/packet-protocols/linux_sll
|
||||
@load base/packet-protocols/nflog
|
||||
@load base/packet-protocols/null
|
||||
@load base/packet-protocols/ppp_serial
|
||||
@load base/packet-protocols/pppoe
|
||||
@load base/packet-protocols/vlan
|
||||
@load base/packet-protocols/mpls
|
1
scripts/base/packet-protocols/ethernet/__load__.zeek
Normal file
1
scripts/base/packet-protocols/ethernet/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
28
scripts/base/packet-protocols/ethernet/main.zeek
Normal file
28
scripts/base/packet-protocols/ethernet/main.zeek
Normal file
|
@ -0,0 +1,28 @@
|
|||
module PacketAnalyzer::ETHERNET;
|
||||
|
||||
export {
|
||||
## Default analyzer
|
||||
const default_analyzer: PacketAnalyzer::Tag = PacketAnalyzer::ANALYZER_IP &redef;
|
||||
|
||||
## IEEE 802.2 SNAP analyzer
|
||||
const snap_analyzer: PacketAnalyzer::Tag &redef;
|
||||
## Novell raw IEEE 802.3 analyzer
|
||||
const novell_raw_analyzer: PacketAnalyzer::Tag &redef;
|
||||
## IEEE 802.2 LLC analyzer
|
||||
const llc_analyzer: PacketAnalyzer::Tag &redef;
|
||||
|
||||
## Identifier mappings based on EtherType
|
||||
const dispatch_map: PacketAnalyzer::DispatchMap = {} &redef;
|
||||
}
|
||||
|
||||
redef dispatch_map += {
|
||||
[0x8847] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_MPLS),
|
||||
[0x0800] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4),
|
||||
[0x86DD] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6),
|
||||
[0x0806] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP),
|
||||
[0x8035] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP),
|
||||
[0x8100] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_VLAN),
|
||||
[0x88A8] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_VLAN),
|
||||
[0x9100] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_VLAN),
|
||||
[0x8864] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_PPPOE)
|
||||
};
|
1
scripts/base/packet-protocols/fddi/__load__.zeek
Normal file
1
scripts/base/packet-protocols/fddi/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
6
scripts/base/packet-protocols/fddi/main.zeek
Normal file
6
scripts/base/packet-protocols/fddi/main.zeek
Normal file
|
@ -0,0 +1,6 @@
|
|||
module PacketAnalyzer::FDDI;
|
||||
|
||||
export {
|
||||
## Default analyzer
|
||||
const default_analyzer: PacketAnalyzer::Tag = PacketAnalyzer::ANALYZER_IP &redef;
|
||||
}
|
1
scripts/base/packet-protocols/ieee802_11/__load__.zeek
Normal file
1
scripts/base/packet-protocols/ieee802_11/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
13
scripts/base/packet-protocols/ieee802_11/main.zeek
Normal file
13
scripts/base/packet-protocols/ieee802_11/main.zeek
Normal file
|
@ -0,0 +1,13 @@
|
|||
module PacketAnalyzer::IEEE802_11;
|
||||
|
||||
export {
|
||||
## Identifier mappings based on EtherType
|
||||
const dispatch_map: PacketAnalyzer::DispatchMap = {} &redef;
|
||||
}
|
||||
|
||||
redef dispatch_map += {
|
||||
[0x0800] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4),
|
||||
[0x86DD] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6),
|
||||
[0x0806] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP),
|
||||
[0x8035] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP)
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
@load ./main
|
12
scripts/base/packet-protocols/ieee802_11_radio/main.zeek
Normal file
12
scripts/base/packet-protocols/ieee802_11_radio/main.zeek
Normal file
|
@ -0,0 +1,12 @@
|
|||
module PacketAnalyzer::IEEE802_11_RADIO;
|
||||
|
||||
export {
|
||||
## Identifier mappings
|
||||
const dispatch_map: PacketAnalyzer::DispatchMap = {} &redef;
|
||||
}
|
||||
|
||||
const DLT_IEEE802_11 : count = 105;
|
||||
|
||||
redef dispatch_map += {
|
||||
[DLT_IEEE802_11] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IEEE802_11)
|
||||
};
|
1
scripts/base/packet-protocols/ip/__load__.zeek
Normal file
1
scripts/base/packet-protocols/ip/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
11
scripts/base/packet-protocols/ip/main.zeek
Normal file
11
scripts/base/packet-protocols/ip/main.zeek
Normal file
|
@ -0,0 +1,11 @@
|
|||
module PacketAnalyzer::IP;
|
||||
|
||||
export {
|
||||
## Identifier mappings based on IP version (4 or 6)
|
||||
const dispatch_map: PacketAnalyzer::DispatchMap = {} &redef;
|
||||
}
|
||||
|
||||
redef dispatch_map += {
|
||||
[4] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4),
|
||||
[6] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6)
|
||||
};
|
1
scripts/base/packet-protocols/linux_sll/__load__.zeek
Normal file
1
scripts/base/packet-protocols/linux_sll/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
14
scripts/base/packet-protocols/linux_sll/main.zeek
Normal file
14
scripts/base/packet-protocols/linux_sll/main.zeek
Normal file
|
@ -0,0 +1,14 @@
|
|||
module PacketAnalyzer::LINUXSLL;
|
||||
|
||||
export {
|
||||
## Identifier mappings based on EtherType
|
||||
const dispatch_map: PacketAnalyzer::DispatchMap = {} &redef;
|
||||
}
|
||||
|
||||
redef dispatch_map += {
|
||||
[0x0800] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4),
|
||||
[0x86DD] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6),
|
||||
[0x0806] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP),
|
||||
# RARP
|
||||
[0x8035] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP)
|
||||
};
|
1
scripts/base/packet-protocols/mpls/__load__.zeek
Normal file
1
scripts/base/packet-protocols/mpls/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
6
scripts/base/packet-protocols/mpls/main.zeek
Normal file
6
scripts/base/packet-protocols/mpls/main.zeek
Normal file
|
@ -0,0 +1,6 @@
|
|||
module PacketAnalyzer::MPLS;
|
||||
|
||||
export {
|
||||
## Default analyzer
|
||||
const default_analyzer: PacketAnalyzer::Tag = PacketAnalyzer::ANALYZER_IP &redef;
|
||||
}
|
1
scripts/base/packet-protocols/nflog/__load__.zeek
Normal file
1
scripts/base/packet-protocols/nflog/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
14
scripts/base/packet-protocols/nflog/main.zeek
Normal file
14
scripts/base/packet-protocols/nflog/main.zeek
Normal file
|
@ -0,0 +1,14 @@
|
|||
module PacketAnalyzer::NFLOG;
|
||||
|
||||
export {
|
||||
## Identifier mappings
|
||||
const dispatch_map: PacketAnalyzer::DispatchMap = {} &redef;
|
||||
}
|
||||
|
||||
const AF_INET : count = 2;
|
||||
const AF_INET6 : count = 10;
|
||||
|
||||
redef dispatch_map += {
|
||||
[AF_INET] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4),
|
||||
[AF_INET6] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6)
|
||||
};
|
1
scripts/base/packet-protocols/null/__load__.zeek
Normal file
1
scripts/base/packet-protocols/null/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
25
scripts/base/packet-protocols/null/main.zeek
Normal file
25
scripts/base/packet-protocols/null/main.zeek
Normal file
|
@ -0,0 +1,25 @@
|
|||
module PacketAnalyzer::NULL;
|
||||
|
||||
export {
|
||||
## Identifier mappings
|
||||
const dispatch_map: PacketAnalyzer::DispatchMap = {} &redef;
|
||||
}
|
||||
|
||||
const DLT_NULL : count = 0;
|
||||
|
||||
redef PacketAnalyzer::ROOT::dispatch_map += {
|
||||
[DLT_NULL] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_NULL)
|
||||
};
|
||||
|
||||
redef dispatch_map += {
|
||||
[2] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4),
|
||||
|
||||
## From the Wireshark Wiki: AF_INET6ANALYZER, unfortunately, has different values in
|
||||
## {NetBSD,OpenBSD,BSD/OS}, {FreeBSD,DragonFlyBSD}, and {Darwin/Mac OS X}, so an IPv6
|
||||
## packet might have a link-layer header with 24, 28, or 30 as the AF_ value. As we
|
||||
## may be reading traces captured on platforms other than what we're running on, we
|
||||
## accept them all here.
|
||||
[24] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6),
|
||||
[28] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6),
|
||||
[30] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6)
|
||||
};
|
1
scripts/base/packet-protocols/ppp_serial/__load__.zeek
Normal file
1
scripts/base/packet-protocols/ppp_serial/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
18
scripts/base/packet-protocols/ppp_serial/main.zeek
Normal file
18
scripts/base/packet-protocols/ppp_serial/main.zeek
Normal file
|
@ -0,0 +1,18 @@
|
|||
module PacketAnalyzer::PPP_SERIAL;
|
||||
|
||||
export {
|
||||
## Identifier mappings
|
||||
const dispatch_map: PacketAnalyzer::DispatchMap = {} &redef;
|
||||
}
|
||||
|
||||
const DLT_PPP_SERIAL : count = 50;
|
||||
|
||||
redef PacketAnalyzer::ROOT::dispatch_map += {
|
||||
[DLT_PPP_SERIAL] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_PPPSERIAL)
|
||||
};
|
||||
|
||||
redef dispatch_map += {
|
||||
[0x0281] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_MPLS),
|
||||
[0x0021] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4),
|
||||
[0x0057] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6)
|
||||
};
|
1
scripts/base/packet-protocols/pppoe/__load__.zeek
Normal file
1
scripts/base/packet-protocols/pppoe/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
11
scripts/base/packet-protocols/pppoe/main.zeek
Normal file
11
scripts/base/packet-protocols/pppoe/main.zeek
Normal file
|
@ -0,0 +1,11 @@
|
|||
module PacketAnalyzer::PPPOE;
|
||||
|
||||
export {
|
||||
## Identifier mappings
|
||||
const dispatch_map: PacketAnalyzer::DispatchMap = {} &redef;
|
||||
}
|
||||
|
||||
redef dispatch_map += {
|
||||
[0x0021] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4),
|
||||
[0x0057] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6)
|
||||
};
|
1
scripts/base/packet-protocols/root/__load__.zeek
Normal file
1
scripts/base/packet-protocols/root/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
26
scripts/base/packet-protocols/root/main.zeek
Normal file
26
scripts/base/packet-protocols/root/main.zeek
Normal file
|
@ -0,0 +1,26 @@
|
|||
module PacketAnalyzer::ROOT;
|
||||
|
||||
export {
|
||||
## Default analyzer (if we don't know the link type, we assume raw IP)
|
||||
const default_analyzer: PacketAnalyzer::Tag = PacketAnalyzer::ANALYZER_IP &redef;
|
||||
|
||||
## Identifier mappings based on link type
|
||||
const dispatch_map: PacketAnalyzer::DispatchMap = {} &redef;
|
||||
}
|
||||
|
||||
const DLT_EN10MB : count = 1;
|
||||
const DLT_FDDI : count = 10;
|
||||
const DLT_IEEE802_11 : count = 105;
|
||||
const DLT_IEEE802_11_RADIO : count = 127;
|
||||
const DLT_LINUX_SLL : count = 113;
|
||||
const DLT_NFLOG : count = 239;
|
||||
|
||||
redef dispatch_map += {
|
||||
[DLT_EN10MB] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ETHERNET),
|
||||
[DLT_FDDI] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_FDDI),
|
||||
[DLT_IEEE802_11] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IEEE802_11),
|
||||
[DLT_IEEE802_11_RADIO] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IEEE802_11_RADIO),
|
||||
[DLT_LINUX_SLL] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_LINUXSLL),
|
||||
[DLT_NFLOG] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_NFLOG)
|
||||
|
||||
};
|
1
scripts/base/packet-protocols/skip/__load__.zeek
Normal file
1
scripts/base/packet-protocols/skip/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
9
scripts/base/packet-protocols/skip/main.zeek
Normal file
9
scripts/base/packet-protocols/skip/main.zeek
Normal file
|
@ -0,0 +1,9 @@
|
|||
module PacketAnalyzer::SKIP;
|
||||
|
||||
export {
|
||||
## Default analyzer
|
||||
const default_analyzer: PacketAnalyzer::Tag = PacketAnalyzer::ANALYZER_IP &redef;
|
||||
|
||||
## Bytes to skip.
|
||||
const skip_bytes: count = 0 &redef;
|
||||
}
|
1
scripts/base/packet-protocols/vlan/__load__.zeek
Normal file
1
scripts/base/packet-protocols/vlan/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
16
scripts/base/packet-protocols/vlan/main.zeek
Normal file
16
scripts/base/packet-protocols/vlan/main.zeek
Normal file
|
@ -0,0 +1,16 @@
|
|||
module PacketAnalyzer::VLAN;
|
||||
|
||||
export {
|
||||
## Identifier mappings based on EtherType
|
||||
const dispatch_map: PacketAnalyzer::DispatchMap = {} &redef;
|
||||
}
|
||||
|
||||
redef dispatch_map += {
|
||||
[0x8847] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_MPLS),
|
||||
[0x0800] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV4),
|
||||
[0x86DD] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_IPV6),
|
||||
[0x0806] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP),
|
||||
[0x8035] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_ARP),
|
||||
[0x8100] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_VLAN),
|
||||
[0x8864] = PacketAnalyzer::DispatchEntry($analyzer=PacketAnalyzer::ANALYZER_PPPOE)
|
||||
};
|
|
@ -146,6 +146,7 @@ set(bro_PLUGIN_LIBS CACHE INTERNAL "plugin libraries" FORCE)
|
|||
set(bro_PLUGIN_DEPS CACHE INTERNAL "plugin dependencies" FORCE)
|
||||
|
||||
add_subdirectory(analyzer)
|
||||
add_subdirectory(packet_analysis)
|
||||
add_subdirectory(broker)
|
||||
add_subdirectory(zeekygen)
|
||||
add_subdirectory(file_analysis)
|
||||
|
|
|
@ -349,8 +349,8 @@ protected:
|
|||
TransportProto proto;
|
||||
uint32_t orig_flow_label, resp_flow_label; // most recent IPv6 flow labels
|
||||
uint32_t vlan, inner_vlan; // VLAN this connection traverses, if available
|
||||
u_char orig_l2_addr[Packet::l2_addr_len]; // Link-layer originator address, if available
|
||||
u_char resp_l2_addr[Packet::l2_addr_len]; // Link-layer responder address, if available
|
||||
u_char orig_l2_addr[Packet::L2_ADDR_LEN]; // Link-layer originator address, if available
|
||||
u_char resp_l2_addr[Packet::L2_ADDR_LEN]; // Link-layer responder address, if available
|
||||
double start_time, last_time;
|
||||
double inactivity_timeout;
|
||||
RecordValPtr conn_val;
|
||||
|
|
|
@ -20,11 +20,12 @@ DebugLogger::Stream DebugLogger::streams[NUM_DBGS] = {
|
|||
{ "notifiers", 0, false },
|
||||
{ "main-loop", 0, false },
|
||||
{ "dpd", 0, false },
|
||||
{ "packet_analysis", 0, false },
|
||||
{ "file_analysis", 0, false },
|
||||
{ "tm", 0, false },
|
||||
{ "logging", 0, false },
|
||||
{ "input", 0, false },
|
||||
{ "threading", 0, false },
|
||||
{ "file_analysis", 0, false },
|
||||
{ "plugins", 0, false },
|
||||
{ "zeekygen", 0, false },
|
||||
{ "pktio", 0, false },
|
||||
|
|
|
@ -36,11 +36,12 @@ enum DebugStream {
|
|||
DBG_NOTIFIERS, // Notifiers
|
||||
DBG_MAINLOOP, // Main IOSource loop
|
||||
DBG_ANALYZER, // Analyzer framework
|
||||
DBG_PACKET_ANALYSIS, // Packet analysis
|
||||
DBG_FILE_ANALYSIS, // File analysis
|
||||
DBG_TM, // Time-machine packet input via Brocolli
|
||||
DBG_LOGGING, // Logging streams
|
||||
DBG_INPUT, // Input streams
|
||||
DBG_THREADING, // Threading system
|
||||
DBG_FILE_ANALYSIS, // File analysis
|
||||
DBG_PLUGINS, // Plugin system
|
||||
DBG_ZEEKYGEN, // Zeekygen
|
||||
DBG_PKTIO, // Packet sources and dumpers.
|
||||
|
|
|
@ -113,8 +113,6 @@ int partial_connection_ok;
|
|||
int tcp_SYN_ack_ok;
|
||||
int tcp_match_undelivered;
|
||||
|
||||
int encap_hdr_size;
|
||||
|
||||
double frag_timeout;
|
||||
|
||||
double tcp_SYN_timeout;
|
||||
|
@ -261,8 +259,6 @@ void init_net_var()
|
|||
tcp_SYN_ack_ok = id::find_val("tcp_SYN_ack_ok")->AsBool();
|
||||
tcp_match_undelivered = id::find_val("tcp_match_undelivered")->AsBool();
|
||||
|
||||
encap_hdr_size = id::find_val("encap_hdr_size")->AsCount();
|
||||
|
||||
frag_timeout = id::find_val("frag_timeout")->AsInterval();
|
||||
|
||||
tcp_SYN_timeout = id::find_val("tcp_SYN_timeout")->AsInterval();
|
||||
|
@ -365,7 +361,6 @@ int& ignore_checksums = zeek::detail::ignore_checksums;
|
|||
int& partial_connection_ok = zeek::detail::partial_connection_ok;
|
||||
int& tcp_SYN_ack_ok = zeek::detail::tcp_SYN_ack_ok;
|
||||
int& tcp_match_undelivered = zeek::detail::tcp_match_undelivered;
|
||||
int& encap_hdr_size = zeek::detail::encap_hdr_size;
|
||||
double& frag_timeout = zeek::detail::frag_timeout;
|
||||
double& tcp_SYN_timeout = zeek::detail::tcp_SYN_timeout;
|
||||
double& tcp_session_timer = zeek::detail::tcp_session_timer;
|
||||
|
|
|
@ -17,8 +17,6 @@ extern int partial_connection_ok;
|
|||
extern int tcp_SYN_ack_ok;
|
||||
extern int tcp_match_undelivered;
|
||||
|
||||
extern int encap_hdr_size;
|
||||
|
||||
extern double frag_timeout;
|
||||
|
||||
extern double tcp_SYN_timeout;
|
||||
|
@ -117,7 +115,6 @@ extern int& ignore_checksums [[deprecated("Remove in v4.1. Use zeek::detail::ign
|
|||
extern int& partial_connection_ok [[deprecated("Remove in v4.1. Use zeek::detail::partial_connection_ok.")]];
|
||||
extern int& tcp_SYN_ack_ok [[deprecated("Remove in v4.1. Use zeek::detail::tcp_SYN_ack_ok.")]];
|
||||
extern int& tcp_match_undelivered [[deprecated("Remove in v4.1. Use zeek::detail::tcp_match_undelivered.")]];
|
||||
extern int& encap_hdr_size [[deprecated("Remove in v4.1. Use zeek::detail::encap_hdr_size.")]];
|
||||
extern double& frag_timeout [[deprecated("Remove in v4.1. Use zeek::detail::frag_timeout.")]];
|
||||
extern double& tcp_SYN_timeout [[deprecated("Remove in v4.1. Use zeek::detail::tcp_SYN_timeout.")]];
|
||||
extern double& tcp_session_timer [[deprecated("Remove in v4.1. Use zeek::detail::tcp_session_timer.")]];
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
|
||||
#include "analyzer/protocol/stepping-stone/SteppingStone.h"
|
||||
#include "analyzer/protocol/stepping-stone/events.bif.h"
|
||||
#include "analyzer/protocol/arp/ARP.h"
|
||||
#include "analyzer/protocol/arp/events.bif.h"
|
||||
#include "Discard.h"
|
||||
#include "RuleMatcher.h"
|
||||
|
||||
|
@ -33,6 +31,8 @@
|
|||
#include "iosource/IOSource.h"
|
||||
#include "iosource/PktDumper.h"
|
||||
|
||||
#include "pcap.h"
|
||||
|
||||
// These represent NetBIOS services on ephemeral ports. They're numbered
|
||||
// so that we can use a single int to hold either an actual TCP/UDP server
|
||||
// port or one of these.
|
||||
|
@ -85,7 +85,6 @@ NetSessions::NetSessions()
|
|||
|
||||
packet_filter = nullptr;
|
||||
|
||||
dump_this_packet = false;
|
||||
num_packets_processed = 0;
|
||||
static auto pkt_profile_file = id::find_val("pkt_profile_file");
|
||||
|
||||
|
@ -96,11 +95,6 @@ NetSessions::NetSessions()
|
|||
else
|
||||
pkt_profiler = nullptr;
|
||||
|
||||
if ( arp_request || arp_reply || bad_arp )
|
||||
arp_analyzer = new analyzer::arp::ARP_Analyzer();
|
||||
else
|
||||
arp_analyzer = nullptr;
|
||||
|
||||
memset(&stats, 0, sizeof(SessionStats));
|
||||
}
|
||||
|
||||
|
@ -108,7 +102,6 @@ NetSessions::~NetSessions()
|
|||
{
|
||||
delete packet_filter;
|
||||
delete pkt_profiler;
|
||||
Unref(arp_analyzer);
|
||||
delete discarder;
|
||||
delete stp_manager;
|
||||
|
||||
|
@ -138,10 +131,15 @@ void NetSessions::NextPacket(double t, const Packet* pkt)
|
|||
|
||||
++num_packets_processed;
|
||||
|
||||
dump_this_packet = false;
|
||||
|
||||
if ( zeek::detail::record_all_packets )
|
||||
bool dumped_packet = false;
|
||||
if ( pkt->dump_packet || zeek::detail::record_all_packets )
|
||||
{
|
||||
DumpPacket(pkt);
|
||||
dumped_packet = true;
|
||||
}
|
||||
|
||||
if ( ! pkt->session_analysis )
|
||||
return;
|
||||
|
||||
if ( pkt->hdr_size > pkt->cap_len )
|
||||
{
|
||||
|
@ -159,7 +157,7 @@ void NetSessions::NextPacket(double t, const Packet* pkt)
|
|||
return;
|
||||
}
|
||||
|
||||
const struct ip* ip = (const struct ip*) (pkt->data + pkt->hdr_size);
|
||||
auto ip = (const struct ip*) (pkt->data + pkt->hdr_size);
|
||||
IP_Hdr ip_hdr(ip, false);
|
||||
DoNextPacket(t, pkt, &ip_hdr, nullptr);
|
||||
}
|
||||
|
@ -176,20 +174,14 @@ void NetSessions::NextPacket(double t, const Packet* pkt)
|
|||
DoNextPacket(t, pkt, &ip_hdr, nullptr);
|
||||
}
|
||||
|
||||
else if ( pkt->l3_proto == L3_ARP )
|
||||
{
|
||||
if ( arp_analyzer )
|
||||
arp_analyzer->NextPacket(t, pkt);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Weird("unknown_packet_type", pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ( dump_this_packet && ! zeek::detail::record_all_packets )
|
||||
// Check whether packet should be recorded based on session analysis
|
||||
if ( pkt->dump_packet && ! dumped_packet )
|
||||
DumpPacket(pkt);
|
||||
}
|
||||
|
||||
|
@ -290,7 +282,7 @@ void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr
|
|||
|
||||
if ( ip_hdr->IsFragment() )
|
||||
{
|
||||
dump_this_packet = true; // always record fragments
|
||||
pkt->dump_packet = true; // always record fragments
|
||||
|
||||
if ( caplen < len )
|
||||
{
|
||||
|
@ -333,7 +325,7 @@ void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr
|
|||
// there, it's always the last.
|
||||
if ( ip_hdr->LastHeader() == IPPROTO_ESP )
|
||||
{
|
||||
dump_this_packet = true;
|
||||
pkt->dump_packet = true;
|
||||
if ( esp_packet )
|
||||
event_mgr.Enqueue(esp_packet, ip_hdr->ToPktHdrVal());
|
||||
|
||||
|
@ -346,7 +338,7 @@ void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr
|
|||
// last if present.
|
||||
if ( ip_hdr->LastHeader() == IPPROTO_MOBILITY )
|
||||
{
|
||||
dump_this_packet = true;
|
||||
pkt->dump_packet = true;
|
||||
|
||||
if ( ! ignore_checksums && mobility_header_checksum(ip_hdr) != 0xffff )
|
||||
{
|
||||
|
@ -735,7 +727,7 @@ void NetSessions::DoNextPacket(double t, const Packet* pkt, const IP_Hdr* ip_hdr
|
|||
else if ( record_packet )
|
||||
{
|
||||
if ( record_content )
|
||||
dump_this_packet = true; // save the whole thing
|
||||
pkt->dump_packet = true; // save the whole thing
|
||||
|
||||
else
|
||||
{
|
||||
|
@ -810,7 +802,7 @@ void NetSessions::DoNextInnerPacket(double t, const Packet* pkt,
|
|||
Packet p;
|
||||
p.Init(link_type, &ts, caplen, len, data, false, "");
|
||||
|
||||
if ( p.Layer2Valid() && (p.l3_proto == L3_IPV4 || p.l3_proto == L3_IPV6) )
|
||||
if ( p.l2_valid && (p.l3_proto == L3_IPV4 || p.l3_proto == L3_IPV6) )
|
||||
{
|
||||
auto inner = p.IP();
|
||||
DoNextPacket(t, &p, &inner, outer);
|
||||
|
@ -1329,7 +1321,7 @@ void NetSessions::Weird(const char* name, const Packet* pkt,
|
|||
const EncapsulationStack* encap, const char* addl)
|
||||
{
|
||||
if ( pkt )
|
||||
dump_this_packet = true;
|
||||
pkt->dump_packet = true;
|
||||
|
||||
if ( encap && encap->LastType() != BifEnum::Tunnel::NONE )
|
||||
reporter->Weird(util::fmt("%s_in_tunnel", name), addl);
|
||||
|
|
|
@ -24,7 +24,6 @@ using ConnID [[deprecated("Remove in v4.1. Use zeek::ConnID.")]] = zeek::ConnID;
|
|||
|
||||
ZEEK_FORWARD_DECLARE_NAMESPACED(Discarder, zeek::detail);
|
||||
ZEEK_FORWARD_DECLARE_NAMESPACED(SteppingStoneManager, zeek, analyzer::stepping_stone);
|
||||
ZEEK_FORWARD_DECLARE_NAMESPACED(ARP_Analyzer, zeek, analyzer::arp);
|
||||
|
||||
namespace zeek {
|
||||
|
||||
|
@ -234,14 +233,11 @@ protected:
|
|||
using IPTunnelMap = std::map<IPPair, TunnelActivity>;
|
||||
IPTunnelMap ip_tunnels;
|
||||
|
||||
analyzer::arp::ARP_Analyzer* arp_analyzer;
|
||||
|
||||
analyzer::stepping_stone::SteppingStoneManager* stp_manager;
|
||||
detail::Discarder* discarder;
|
||||
detail::PacketFilter* packet_filter;
|
||||
uint64_t num_packets_processed;
|
||||
detail::PacketProfiler* pkt_profiler;
|
||||
bool dump_this_packet; // if true, current packet should be recorded
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
add_subdirectory(arp)
|
||||
add_subdirectory(ayiya)
|
||||
add_subdirectory(bittorrent)
|
||||
add_subdirectory(conn-size)
|
||||
|
|
|
@ -1,244 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "ARP.h"
|
||||
#include "Event.h"
|
||||
#include "Reporter.h"
|
||||
#include "Desc.h"
|
||||
|
||||
#include "events.bif.h"
|
||||
|
||||
namespace zeek::analyzer::arp {
|
||||
|
||||
ARP_Analyzer::ARP_Analyzer()
|
||||
{
|
||||
}
|
||||
|
||||
ARP_Analyzer::~ARP_Analyzer()
|
||||
{
|
||||
}
|
||||
|
||||
// Argh! FreeBSD and Linux have almost completely different net/if_arp.h .
|
||||
// ... and on Solaris we are missing half of the ARPOP codes, so define
|
||||
// them here as necessary:
|
||||
|
||||
#ifndef ARPOP_REQUEST
|
||||
#define ARPOP_REQUEST 1 // ARP request.
|
||||
#endif
|
||||
#ifndef ARPOP_REPLY
|
||||
#define ARPOP_REPLY 2 // ARP reply.
|
||||
#endif
|
||||
#ifndef ARPOP_PREQUEST
|
||||
#define ARPOP_RREQUEST 3 // RARP request.
|
||||
#endif
|
||||
#ifndef ARPOP_RREPLY
|
||||
#define ARPOP_RREPLY 4 // RARP reply.
|
||||
#endif
|
||||
#ifndef ARPOP_InREQUEST
|
||||
#define ARPOP_InREQUEST 8 // InARP request.
|
||||
#endif
|
||||
#ifndef ARPOP_InREPLY
|
||||
#define ARPOP_InREPLY 9 // InARP reply.
|
||||
#endif
|
||||
#ifndef ARPOP_NAK
|
||||
#define ARPOP_NAK 10 // (ATM)ARP NAK.
|
||||
#endif
|
||||
|
||||
#ifndef ar_sha
|
||||
#define ar_sha(ap) ((caddr_t((ap)+1)) + 0)
|
||||
#endif
|
||||
|
||||
#ifndef ar_spa
|
||||
#define ar_spa(ap) ((caddr_t((ap)+1)) + (ap)->ar_hln)
|
||||
#endif
|
||||
|
||||
#ifndef ar_tha
|
||||
#define ar_tha(ap) ((caddr_t((ap)+1)) + (ap)->ar_hln + (ap)->ar_pln)
|
||||
#endif
|
||||
|
||||
#ifndef ar_tpa
|
||||
#define ar_tpa(ap) ((caddr_t((ap)+1)) + 2*(ap)->ar_hln + (ap)->ar_pln)
|
||||
#endif
|
||||
|
||||
#ifndef ARPOP_REVREQUEST
|
||||
#define ARPOP_REVREQUEST ARPOP_RREQUEST
|
||||
#endif
|
||||
|
||||
#ifndef ARPOP_REVREPLY
|
||||
#define ARPOP_REVREPLY ARPOP_RREPLY
|
||||
#endif
|
||||
|
||||
#ifndef ARPOP_INVREQUEST
|
||||
#define ARPOP_INVREQUEST ARPOP_InREQUEST
|
||||
#endif
|
||||
|
||||
#ifndef ARPOP_INVREPLY
|
||||
#define ARPOP_INVREPLY ARPOP_InREPLY
|
||||
#endif
|
||||
|
||||
|
||||
void ARP_Analyzer::NextPacket(double t, const Packet* pkt)
|
||||
{
|
||||
const u_char *data = pkt->data;
|
||||
// Check whether the packet is OK ("inspired" in tcpdump's print-arp.c).
|
||||
const struct arp_pkthdr* ah =
|
||||
(const struct arp_pkthdr*) (data + pkt->hdr_size);
|
||||
|
||||
// Check the size.
|
||||
int min_length = (ar_tpa(ah) - (char*) (data + pkt->hdr_size)) + ah->ar_pln;
|
||||
int real_length = pkt->cap_len - pkt->hdr_size;
|
||||
if ( min_length > real_length )
|
||||
{
|
||||
Corrupted("truncated_ARP");
|
||||
return;
|
||||
}
|
||||
|
||||
char errbuf[1024];
|
||||
|
||||
// Check the address description fields.
|
||||
switch ( ntohs(ah->ar_hrd) ) {
|
||||
case ARPHRD_ETHER:
|
||||
if ( ah->ar_hln != 6 )
|
||||
{ // don't know how to handle the opcode
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"corrupt-arp-header (hrd=%i, hln=%i)",
|
||||
ntohs(ah->ar_hrd), ah->ar_hln);
|
||||
BadARP(ah, errbuf);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{ // don't know how to proceed
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"unknown-arp-hw-address (hrd=%i)", ntohs(ah->ar_hrd));
|
||||
BadARP(ah, errbuf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ### Note, we don't support IPv6 addresses yet.
|
||||
switch ( ntohs(ah->ar_pro) ) {
|
||||
case ETHERTYPE_IP:
|
||||
if ( ah->ar_pln != 4 )
|
||||
{ // don't know how to handle the opcode
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"corrupt-arp-header (pro=%i, pln=%i)",
|
||||
ntohs(ah->ar_pro), ah->ar_pln);
|
||||
BadARP(ah, errbuf);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{ // don't know how to proceed
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"unknown-arp-proto-address (pro=%i)",
|
||||
ntohs(ah->ar_pro));
|
||||
BadARP(ah, errbuf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check MAC src address = ARP sender MAC address.
|
||||
if ( memcmp(pkt->l2_src, ar_sha(ah), ah->ar_hln) )
|
||||
{
|
||||
BadARP(ah, "weird-arp-sha");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the code is supported.
|
||||
switch ( ntohs(ah->ar_op) ) {
|
||||
case ARPOP_REQUEST:
|
||||
RREvent(arp_request, pkt->l2_src, pkt->l2_dst,
|
||||
ar_spa(ah), ar_sha(ah), ar_tpa(ah), ar_tha(ah));
|
||||
break;
|
||||
|
||||
case ARPOP_REPLY:
|
||||
RREvent(arp_reply, pkt->l2_src, pkt->l2_dst,
|
||||
ar_spa(ah), ar_sha(ah), ar_tpa(ah), ar_tha(ah));
|
||||
break;
|
||||
|
||||
case ARPOP_REVREQUEST:
|
||||
case ARPOP_REVREPLY:
|
||||
case ARPOP_INVREQUEST:
|
||||
case ARPOP_INVREPLY:
|
||||
{ // don't know how to handle the opcode
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"unimplemented-arp-opcode (%i)", ntohs(ah->ar_op));
|
||||
BadARP(ah, errbuf);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{ // invalid opcode
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"invalid-arp-opcode (opcode=%i)", ntohs(ah->ar_op));
|
||||
BadARP(ah, errbuf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ARP_Analyzer::Describe(ODesc* d) const
|
||||
{
|
||||
d->Add("<ARP analyzer>");
|
||||
d->NL();
|
||||
}
|
||||
|
||||
void ARP_Analyzer::BadARP(const struct arp_pkthdr* hdr, const char* msg)
|
||||
{
|
||||
if ( ! bad_arp )
|
||||
return;
|
||||
|
||||
event_mgr.Enqueue(bad_arp,
|
||||
ToAddrVal(ar_spa(hdr)),
|
||||
ToEthAddrStr((const u_char*) ar_sha(hdr)),
|
||||
ToAddrVal(ar_tpa(hdr)),
|
||||
ToEthAddrStr((const u_char*) ar_tha(hdr)),
|
||||
make_intrusive<StringVal>(msg));
|
||||
}
|
||||
|
||||
void ARP_Analyzer::Corrupted(const char* msg)
|
||||
{
|
||||
reporter->Weird(msg);
|
||||
}
|
||||
|
||||
void ARP_Analyzer::RREvent(EventHandlerPtr e,
|
||||
const u_char* src, const u_char *dst,
|
||||
const char* spa, const char* sha,
|
||||
const char* tpa, const char* tha)
|
||||
{
|
||||
if ( ! e )
|
||||
return;
|
||||
|
||||
event_mgr.Enqueue(e,
|
||||
ToEthAddrStr(src),
|
||||
ToEthAddrStr(dst),
|
||||
ToAddrVal(spa),
|
||||
ToEthAddrStr((const u_char*) sha),
|
||||
ToAddrVal(tpa),
|
||||
ToEthAddrStr((const u_char*) tha));
|
||||
}
|
||||
|
||||
AddrVal* ARP_Analyzer::ConstructAddrVal(const void* addr)
|
||||
{ return ToAddrVal(addr).release(); }
|
||||
|
||||
AddrValPtr ARP_Analyzer::ToAddrVal(const void* addr)
|
||||
{
|
||||
// ### For now, we only handle IPv4 addresses.
|
||||
return make_intrusive<AddrVal>(*(const uint32_t*) addr);
|
||||
}
|
||||
|
||||
StringVal* ARP_Analyzer::EthAddrToStr(const u_char* addr)
|
||||
{ return ToEthAddrStr(addr).release(); }
|
||||
|
||||
StringValPtr ARP_Analyzer::ToEthAddrStr(const u_char* addr)
|
||||
{
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
||||
return make_intrusive<StringVal>(buf);
|
||||
}
|
||||
|
||||
} // namespace zeek::analyzer::arp
|
|
@ -1,66 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "zeek-config.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#ifdef HAVE_NET_ETHERNET_H
|
||||
#include <net/ethernet.h>
|
||||
#elif defined(HAVE_SYS_ETHERNET_H)
|
||||
#include <sys/ethernet.h>
|
||||
#elif defined(HAVE_NETINET_IF_ETHER_H)
|
||||
#include <netinet/if_ether.h>
|
||||
#elif defined(HAVE_NET_ETHERTYPES_H)
|
||||
#include <net/ethertypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef arp_pkthdr
|
||||
#define arp_pkthdr arphdr
|
||||
#endif
|
||||
|
||||
#include "NetVar.h"
|
||||
|
||||
ZEEK_FORWARD_DECLARE_NAMESPACED(Packet, zeek);
|
||||
|
||||
extern "C" {
|
||||
#include <pcap.h>
|
||||
}
|
||||
|
||||
namespace zeek::analyzer::arp {
|
||||
|
||||
class ARP_Analyzer : public Obj {
|
||||
public:
|
||||
ARP_Analyzer();
|
||||
~ARP_Analyzer() override;
|
||||
|
||||
void NextPacket(double t, const Packet* pkt);
|
||||
|
||||
void Describe(ODesc* d) const override;
|
||||
void RREvent(EventHandlerPtr e, const u_char* src, const u_char* dst,
|
||||
const char* spa, const char* sha,
|
||||
const char* tpa, const char* tha);
|
||||
|
||||
protected:
|
||||
|
||||
[[deprecated("Remove in v4.1. Use ToAddrVal().")]]
|
||||
AddrVal* ConstructAddrVal(const void* addr);
|
||||
[[deprecated("Remove in v4.1. Use ToEthAddrStr().")]]
|
||||
StringVal* EthAddrToStr(const u_char* addr);
|
||||
|
||||
AddrValPtr ToAddrVal(const void* addr);
|
||||
StringValPtr ToEthAddrStr(const u_char* addr);
|
||||
void BadARP(const struct arp_pkthdr* hdr, const char* string);
|
||||
void Corrupted(const char* string);
|
||||
};
|
||||
|
||||
} // namespace zeek::analyzer::arp
|
||||
|
||||
namespace analyzer::arp {
|
||||
|
||||
using ARP_Analyzer [[deprecated("Remove in v4.1. Use zeek::analyzer::arp::ARP_Analyzer.")]] = zeek::analyzer::arp::ARP_Analyzer;
|
||||
|
||||
} // namespace analyzer::arp
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
# This is not an actual analyzer, but used by the core. We still
|
||||
# maintain it here along with the other analyzers because conceptually
|
||||
# it's also parsing a protocol just like them. The current structure
|
||||
# is merely a left-over from when this code was written.
|
||||
|
||||
include(ZeekPlugin)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
zeek_plugin_begin(Zeek ARP)
|
||||
zeek_plugin_cc(ARP.cc Plugin.cc)
|
||||
zeek_plugin_bif(events.bif)
|
||||
zeek_plugin_end()
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
// See the file in the main distribution directory for copyright.
|
||||
|
||||
#include "plugin/Plugin.h"
|
||||
|
||||
namespace zeek::plugin::detail::Zeek_ARP {
|
||||
|
||||
class Plugin : public zeek::plugin::Plugin {
|
||||
public:
|
||||
zeek::plugin::Configuration Configure() override
|
||||
{
|
||||
zeek::plugin::Configuration config;
|
||||
config.name = "Zeek::ARP";
|
||||
config.description = "ARP Parsing";
|
||||
return config;
|
||||
}
|
||||
} plugin;
|
||||
|
||||
} // namespace zeek::plugin::detail::Zeek_ARP
|
|
@ -65,7 +65,7 @@ void VXLAN_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
|
|||
ts.tv_usec = (suseconds_t) ((run_state::current_timestamp - (double)ts.tv_sec) * 1000000);
|
||||
Packet pkt(DLT_EN10MB, &ts, caplen, len, data);
|
||||
|
||||
if ( ! pkt.Layer2Valid() )
|
||||
if ( ! pkt.l2_valid )
|
||||
{
|
||||
ProtocolViolation("VXLAN invalid inner ethernet frame",
|
||||
(const char*) data, len);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "Desc.h"
|
||||
#include "IP.h"
|
||||
#include "iosource/Manager.h"
|
||||
#include "packet_analysis/Manager.h"
|
||||
#include "Var.h"
|
||||
|
||||
extern "C" {
|
||||
|
@ -44,8 +45,11 @@ void Packet::Init(int arg_link_type, pkt_timeval *arg_ts, uint32_t arg_caplen,
|
|||
else
|
||||
data = arg_data;
|
||||
|
||||
session_analysis = false;
|
||||
dump_packet = false;
|
||||
|
||||
time = ts.tv_sec + double(ts.tv_usec) / 1e6;
|
||||
hdr_size = GetLinkHeaderSize(arg_link_type);
|
||||
hdr_size = 0;
|
||||
eth_type = 0;
|
||||
vlan = 0;
|
||||
inner_vlan = 0;
|
||||
|
@ -58,14 +62,13 @@ void Packet::Init(int arg_link_type, pkt_timeval *arg_ts, uint32_t arg_caplen,
|
|||
l3_proto = L3_UNKNOWN;
|
||||
l3_checksummed = false;
|
||||
|
||||
if ( data && cap_len < hdr_size )
|
||||
{
|
||||
Weird("truncated_link_header");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( data )
|
||||
ProcessLayer2();
|
||||
{
|
||||
// From here we assume that layer 2 is valid. If the packet analysis fails,
|
||||
// the packet manager will invalidate the packet.
|
||||
l2_valid = true;
|
||||
packet_mgr->ProcessPacket(this);
|
||||
}
|
||||
}
|
||||
|
||||
const IP_Hdr Packet::IP() const
|
||||
|
@ -76,521 +79,6 @@ const IP_Hdr Packet::IP() const
|
|||
void Packet::Weird(const char* name)
|
||||
{
|
||||
sessions->Weird(name, this);
|
||||
l2_valid = false;
|
||||
}
|
||||
|
||||
int Packet::GetLinkHeaderSize(int link_type)
|
||||
{
|
||||
switch ( link_type ) {
|
||||
case DLT_NULL:
|
||||
return 4;
|
||||
|
||||
case DLT_EN10MB:
|
||||
return 14;
|
||||
|
||||
case DLT_FDDI:
|
||||
return 13 + 8; // fddi_header + LLC
|
||||
|
||||
#ifdef DLT_LINUX_SLL
|
||||
case DLT_LINUX_SLL:
|
||||
return 16;
|
||||
#endif
|
||||
|
||||
case DLT_PPP_SERIAL: // PPP_SERIAL
|
||||
return 4;
|
||||
|
||||
case DLT_IEEE802_11: // 802.11 monitor
|
||||
return 34;
|
||||
|
||||
case DLT_IEEE802_11_RADIO: // 802.11 plus RadioTap
|
||||
return 59;
|
||||
|
||||
case DLT_NFLOG:
|
||||
// Linux netlink NETLINK NFLOG socket log messages
|
||||
// The actual header size is variable, but we return the minimum
|
||||
// expected size here, which is 4 bytes for the main header plus at
|
||||
// least 2 bytes each for the type and length values assoicated with
|
||||
// the final TLV carrying the packet payload.
|
||||
return 8;
|
||||
|
||||
case DLT_RAW:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Packet::ProcessLayer2()
|
||||
{
|
||||
l2_valid = true;
|
||||
|
||||
// Unfortunately some packets on the link might have MPLS labels
|
||||
// while others don't. That means we need to ask the link-layer if
|
||||
// labels are in place.
|
||||
bool have_mpls = false;
|
||||
|
||||
const u_char* pdata = data;
|
||||
const u_char* end_of_data = data + cap_len;
|
||||
|
||||
switch ( link_type ) {
|
||||
case DLT_NULL:
|
||||
{
|
||||
int protocol = (pdata[3] << 24) + (pdata[2] << 16) + (pdata[1] << 8) + pdata[0];
|
||||
pdata += GetLinkHeaderSize(link_type);
|
||||
|
||||
// From the Wireshark Wiki: "AF_INET6, unfortunately, has
|
||||
// different values in {NetBSD,OpenBSD,BSD/OS},
|
||||
// {FreeBSD,DragonFlyBSD}, and {Darwin/Mac OS X}, so an IPv6
|
||||
// packet might have a link-layer header with 24, 28, or 30
|
||||
// as the AF_ value." As we may be reading traces captured on
|
||||
// platforms other than what we're running on, we accept them
|
||||
// all here.
|
||||
|
||||
if ( protocol == AF_INET )
|
||||
l3_proto = L3_IPV4;
|
||||
else if ( protocol == 24 || protocol == 28 || protocol == 30 )
|
||||
l3_proto = L3_IPV6;
|
||||
else
|
||||
{
|
||||
Weird("non_ip_packet_in_null_transport");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DLT_EN10MB:
|
||||
{
|
||||
// Skip past Cisco FabricPath to encapsulated ethernet frame.
|
||||
if ( pdata[12] == 0x89 && pdata[13] == 0x03 )
|
||||
{
|
||||
auto constexpr cfplen = 16;
|
||||
|
||||
if ( pdata + cfplen + GetLinkHeaderSize(link_type) >= end_of_data )
|
||||
{
|
||||
Weird("truncated_link_header_cfp");
|
||||
return;
|
||||
}
|
||||
|
||||
pdata += cfplen;
|
||||
}
|
||||
|
||||
// Get protocol being carried from the ethernet frame.
|
||||
int protocol = (pdata[12] << 8) + pdata[13];
|
||||
|
||||
eth_type = protocol;
|
||||
l2_dst = pdata;
|
||||
l2_src = pdata + 6;
|
||||
|
||||
pdata += GetLinkHeaderSize(link_type);
|
||||
|
||||
bool saw_vlan = false;
|
||||
|
||||
while ( protocol == 0x8100 || protocol == 0x9100 ||
|
||||
protocol == 0x8864 )
|
||||
{
|
||||
switch ( protocol )
|
||||
{
|
||||
// VLAN carried over the ethernet frame.
|
||||
// 802.1q / 802.1ad
|
||||
case 0x8100:
|
||||
case 0x9100:
|
||||
{
|
||||
if ( pdata + 4 >= end_of_data )
|
||||
{
|
||||
Weird("truncated_link_header");
|
||||
return;
|
||||
}
|
||||
|
||||
auto& vlan_ref = saw_vlan ? inner_vlan : vlan;
|
||||
vlan_ref = ((pdata[0] << 8) + pdata[1]) & 0xfff;
|
||||
protocol = ((pdata[2] << 8) + pdata[3]);
|
||||
pdata += 4; // Skip the vlan header
|
||||
saw_vlan = true;
|
||||
eth_type = protocol;
|
||||
}
|
||||
break;
|
||||
|
||||
// PPPoE carried over the ethernet frame.
|
||||
case 0x8864:
|
||||
{
|
||||
if ( pdata + 8 >= end_of_data )
|
||||
{
|
||||
Weird("truncated_link_header");
|
||||
return;
|
||||
}
|
||||
|
||||
protocol = (pdata[6] << 8) + pdata[7];
|
||||
pdata += 8; // Skip the PPPoE session and PPP header
|
||||
|
||||
if ( protocol == 0x0021 )
|
||||
l3_proto = L3_IPV4;
|
||||
else if ( protocol == 0x0057 )
|
||||
l3_proto = L3_IPV6;
|
||||
else
|
||||
{
|
||||
// Neither IPv4 nor IPv6.
|
||||
Weird("non_ip_packet_in_pppoe_encapsulation");
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for MPLS in VLAN.
|
||||
if ( protocol == 0x8847 )
|
||||
have_mpls = true;
|
||||
|
||||
// Normal path to determine Layer 3 protocol.
|
||||
if ( ! have_mpls && l3_proto == L3_UNKNOWN )
|
||||
{
|
||||
if ( protocol == 0x800 )
|
||||
l3_proto = L3_IPV4;
|
||||
else if ( protocol == 0x86dd )
|
||||
l3_proto = L3_IPV6;
|
||||
else if ( protocol == 0x0806 || protocol == 0x8035 )
|
||||
l3_proto = L3_ARP;
|
||||
else
|
||||
{
|
||||
// Neither IPv4 nor IPv6.
|
||||
Weird("non_ip_packet_in_ethernet");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DLT_PPP_SERIAL:
|
||||
{
|
||||
// Get PPP protocol.
|
||||
int protocol = (pdata[2] << 8) + pdata[3];
|
||||
pdata += GetLinkHeaderSize(link_type);
|
||||
|
||||
if ( protocol == 0x0281 )
|
||||
{
|
||||
// MPLS Unicast. Remove the pdata link layer and
|
||||
// denote a header size of zero before the IP header.
|
||||
have_mpls = true;
|
||||
}
|
||||
else if ( protocol == 0x0021 )
|
||||
l3_proto = L3_IPV4;
|
||||
else if ( protocol == 0x0057 )
|
||||
l3_proto = L3_IPV6;
|
||||
else
|
||||
{
|
||||
// Neither IPv4 nor IPv6.
|
||||
Weird("non_ip_packet_in_ppp_encapsulation");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DLT_IEEE802_11_RADIO:
|
||||
{
|
||||
if ( pdata + 3 >= end_of_data )
|
||||
{
|
||||
Weird("truncated_radiotap_header");
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip over the RadioTap header
|
||||
int rtheader_len = (pdata[3] << 8) + pdata[2];
|
||||
|
||||
if ( pdata + rtheader_len >= end_of_data )
|
||||
{
|
||||
Weird("truncated_radiotap_header");
|
||||
return;
|
||||
}
|
||||
|
||||
pdata += rtheader_len;
|
||||
// fallthrough
|
||||
}
|
||||
|
||||
case DLT_IEEE802_11:
|
||||
{
|
||||
u_char len_80211 = 24; // minimal length of data frames
|
||||
|
||||
if ( pdata + len_80211 >= end_of_data )
|
||||
{
|
||||
Weird("truncated_802_11_header");
|
||||
return;
|
||||
}
|
||||
|
||||
u_char fc_80211 = pdata[0]; // Frame Control field
|
||||
|
||||
// Skip non-data frame types (management & control).
|
||||
if ( ! ((fc_80211 >> 2) & 0x02) )
|
||||
return;
|
||||
|
||||
// Skip subtypes without data.
|
||||
if ( (fc_80211 >> 4) & 0x04 )
|
||||
return;
|
||||
|
||||
// 'To DS' and 'From DS' flags set indicate use of the 4th
|
||||
// address field.
|
||||
if ( (pdata[1] & 0x03) == 0x03 )
|
||||
len_80211 += l2_addr_len;
|
||||
|
||||
// Look for the QoS indicator bit.
|
||||
if ( (fc_80211 >> 4) & 0x08 )
|
||||
{
|
||||
// Skip in case of A-MSDU subframes indicated by QoS
|
||||
// control field.
|
||||
if ( pdata[len_80211] & 0x80)
|
||||
return;
|
||||
|
||||
len_80211 += 2;
|
||||
}
|
||||
|
||||
if ( pdata + len_80211 >= end_of_data )
|
||||
{
|
||||
Weird("truncated_802_11_header");
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine link-layer addresses based
|
||||
// on 'To DS' and 'From DS' flags
|
||||
switch ( pdata[1] & 0x03 ) {
|
||||
case 0x00:
|
||||
l2_src = pdata + 10;
|
||||
l2_dst = pdata + 4;
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
l2_src = pdata + 10;
|
||||
l2_dst = pdata + 16;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
l2_src = pdata + 16;
|
||||
l2_dst = pdata + 4;
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
l2_src = pdata + 24;
|
||||
l2_dst = pdata + 16;
|
||||
break;
|
||||
}
|
||||
|
||||
// skip 802.11 data header
|
||||
pdata += len_80211;
|
||||
|
||||
if ( pdata + 8 >= end_of_data )
|
||||
{
|
||||
Weird("truncated_802_11_header");
|
||||
return;
|
||||
}
|
||||
// Check that the DSAP and SSAP are both SNAP and that the control
|
||||
// field indicates that this is an unnumbered frame.
|
||||
// The organization code (24bits) needs to also be zero to
|
||||
// indicate that this is encapsulated ethernet.
|
||||
if ( pdata[0] == 0xAA && pdata[1] == 0xAA && pdata[2] == 0x03 &&
|
||||
pdata[3] == 0 && pdata[4] == 0 && pdata[5] == 0 )
|
||||
{
|
||||
pdata += 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this is a logical link control frame without the
|
||||
// possibility of having a protocol we care about, we'll
|
||||
// just skip it for now.
|
||||
return;
|
||||
}
|
||||
|
||||
int protocol = (pdata[0] << 8) + pdata[1];
|
||||
if ( protocol == 0x0800 )
|
||||
l3_proto = L3_IPV4;
|
||||
else if ( protocol == 0x86DD )
|
||||
l3_proto = L3_IPV6;
|
||||
else if ( protocol == 0x0806 || protocol == 0x8035 )
|
||||
l3_proto = L3_ARP;
|
||||
else
|
||||
{
|
||||
Weird("non_ip_packet_in_ieee802_11");
|
||||
return;
|
||||
}
|
||||
pdata += 2;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DLT_NFLOG:
|
||||
{
|
||||
// See https://www.tcpdump.org/linktypes/LINKTYPE_NFLOG.html
|
||||
|
||||
uint8_t protocol = pdata[0];
|
||||
|
||||
if ( protocol == AF_INET )
|
||||
l3_proto = L3_IPV4;
|
||||
else if ( protocol == AF_INET6 )
|
||||
l3_proto = L3_IPV6;
|
||||
else
|
||||
{
|
||||
Weird("non_ip_in_nflog");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t version = pdata[1];
|
||||
|
||||
if ( version != 0 )
|
||||
{
|
||||
Weird("unknown_nflog_version");
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip to TLVs.
|
||||
pdata += 4;
|
||||
|
||||
uint16_t tlv_len;
|
||||
uint16_t tlv_type;
|
||||
|
||||
while ( true )
|
||||
{
|
||||
if ( pdata + 4 >= end_of_data )
|
||||
{
|
||||
Weird("nflog_no_pcap_payload");
|
||||
return;
|
||||
}
|
||||
|
||||
// TLV Type and Length values are specified in host byte order
|
||||
// (libpcap should have done any needed byteswapping already).
|
||||
|
||||
tlv_len = *(reinterpret_cast<const uint16_t*>(pdata));
|
||||
tlv_type = *(reinterpret_cast<const uint16_t*>(pdata + 2));
|
||||
|
||||
auto constexpr nflog_type_payload = 9;
|
||||
|
||||
if ( tlv_type == nflog_type_payload )
|
||||
{
|
||||
// The raw packet payload follows this TLV.
|
||||
pdata += 4;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The Length value includes the 4 octets for the Type and
|
||||
// Length values, but TLVs are also implicitly padded to
|
||||
// 32-bit alignments (that padding may not be included in
|
||||
// the Length value).
|
||||
|
||||
if ( tlv_len < 4 )
|
||||
{
|
||||
Weird("nflog_bad_tlv_len");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto rem = tlv_len % 4;
|
||||
|
||||
if ( rem != 0 )
|
||||
tlv_len += 4 - rem;
|
||||
}
|
||||
|
||||
pdata += tlv_len;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// Assume we're pointing at IP. Just figure out which version.
|
||||
pdata += GetLinkHeaderSize(link_type);
|
||||
if ( pdata + sizeof(struct ip) >= end_of_data )
|
||||
{
|
||||
Weird("truncated_link_header");
|
||||
return;
|
||||
}
|
||||
|
||||
const struct ip* ip = (const struct ip *)pdata;
|
||||
|
||||
if ( ip->ip_v == 4 )
|
||||
l3_proto = L3_IPV4;
|
||||
else if ( ip->ip_v == 6 )
|
||||
l3_proto = L3_IPV6;
|
||||
else
|
||||
{
|
||||
// Neither IPv4 nor IPv6.
|
||||
Weird("non_ip_packet");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( have_mpls )
|
||||
{
|
||||
// Skip the MPLS label stack.
|
||||
bool end_of_stack = false;
|
||||
|
||||
while ( ! end_of_stack )
|
||||
{
|
||||
if ( pdata + 4 >= end_of_data )
|
||||
{
|
||||
Weird("truncated_link_header");
|
||||
return;
|
||||
}
|
||||
|
||||
end_of_stack = *(pdata + 2) & 0x01;
|
||||
pdata += 4;
|
||||
}
|
||||
|
||||
// We assume that what remains is IP
|
||||
if ( pdata + sizeof(struct ip) >= end_of_data )
|
||||
{
|
||||
Weird("no_ip_in_mpls_payload");
|
||||
return;
|
||||
}
|
||||
|
||||
const struct ip* ip = (const struct ip *)pdata;
|
||||
|
||||
if ( ip->ip_v == 4 )
|
||||
l3_proto = L3_IPV4;
|
||||
else if ( ip->ip_v == 6 )
|
||||
l3_proto = L3_IPV6;
|
||||
else
|
||||
{
|
||||
// Neither IPv4 nor IPv6.
|
||||
Weird("no_ip_in_mpls_payload");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else if ( zeek::detail::encap_hdr_size )
|
||||
{
|
||||
// Blanket encapsulation. We assume that what remains is IP.
|
||||
if ( pdata + zeek::detail::encap_hdr_size + sizeof(struct ip) >= end_of_data )
|
||||
{
|
||||
Weird("no_ip_left_after_encap");
|
||||
return;
|
||||
}
|
||||
|
||||
pdata += zeek::detail::encap_hdr_size;
|
||||
|
||||
const struct ip* ip = (const struct ip *)pdata;
|
||||
|
||||
if ( ip->ip_v == 4 )
|
||||
l3_proto = L3_IPV4;
|
||||
else if ( ip->ip_v == 6 )
|
||||
l3_proto = L3_IPV6;
|
||||
else
|
||||
{
|
||||
// Neither IPv4 nor IPv6.
|
||||
Weird("no_ip_in_encap");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We've now determined (a) L3_IPV4 vs (b) L3_IPV6 vs (c) L3_ARP vs
|
||||
// (d) L3_UNKNOWN.
|
||||
|
||||
// Calculate how much header we've used up.
|
||||
hdr_size = (pdata - data);
|
||||
}
|
||||
|
||||
RecordValPtr Packet::ToRawPktHdrVal() const
|
||||
|
@ -613,6 +101,7 @@ RecordValPtr Packet::ToRawPktHdrVal() const
|
|||
else if ( l3_proto == L3_ARP )
|
||||
l3 = BifEnum::L3_ARP;
|
||||
|
||||
// TODO: Get rid of hardcoded l3 protocols.
|
||||
// l2_hdr layout:
|
||||
// encap: link_encap; ##< L2 link encapsulation
|
||||
// len: count; ##< Total frame length on wire
|
||||
|
@ -683,12 +172,4 @@ ValPtr Packet::FmtEUI48(const u_char* mac) const
|
|||
return make_intrusive<StringVal>(buf);
|
||||
}
|
||||
|
||||
void Packet::Describe(ODesc* d) const
|
||||
{
|
||||
const IP_Hdr ip = IP();
|
||||
d->Add(ip.SrcAddr());
|
||||
d->Add("->");
|
||||
d->Add(ip.DstAddr());
|
||||
}
|
||||
|
||||
} // namespace zeek
|
||||
|
|
|
@ -116,18 +116,9 @@ public:
|
|||
uint32_t len, const u_char *data, bool copy = false,
|
||||
std::string tag = std::string(""));
|
||||
|
||||
/**
|
||||
* Returns true if parsing the layer 2 fields failed, including when
|
||||
* no data was passed into the constructor in the first place.
|
||||
*/
|
||||
bool Layer2Valid() const
|
||||
{
|
||||
return l2_valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interprets the Layer 3 of the packet as IP and returns a
|
||||
* correspondign object.
|
||||
* corresponding object.
|
||||
*/
|
||||
const IP_Hdr IP() const;
|
||||
|
||||
|
@ -140,25 +131,17 @@ public:
|
|||
[[deprecated("Remove in v4.1. Use ToRawPktHdrval() instead.")]]
|
||||
RecordVal* BuildPktHdrVal() const;
|
||||
|
||||
/**
|
||||
* Static method returning the link-layer header size for a given
|
||||
* link type.
|
||||
*
|
||||
* @param link_type The link tyoe.
|
||||
*
|
||||
* @return The header size in bytes, or -1 if not known.
|
||||
*/
|
||||
static int GetLinkHeaderSize(int link_type);
|
||||
|
||||
/**
|
||||
* Describes the packet, with standard signature.
|
||||
*/
|
||||
void Describe(ODesc* d) const;
|
||||
|
||||
/**
|
||||
* Maximal length of a layer 2 address.
|
||||
*/
|
||||
static const int l2_addr_len = 6;
|
||||
static const int L2_ADDR_LEN = 6;
|
||||
|
||||
/**
|
||||
* Empty layer 2 address to be used as default value. For example, the
|
||||
* LinuxSLL packet analyzer doesn't have a destination address in the
|
||||
* header and thus sets it to this default address.
|
||||
*/
|
||||
static constexpr const u_char L2_EMPTY_ADDR[L2_ADDR_LEN] = { 0 };
|
||||
|
||||
// These are passed in through the constructor.
|
||||
std::string tag; /// Used in serialization
|
||||
|
@ -169,46 +152,47 @@ public:
|
|||
uint32_t cap_len; /// Captured packet length
|
||||
uint32_t link_type; /// pcap link_type (DLT_EN10MB, DLT_RAW, etc)
|
||||
|
||||
// True if L2 processing succeeded. If data is set on initialization of
|
||||
// the packet, L2 is assumed to be valid. The packet manager will then
|
||||
// process the packet and set l2_valid to False if the analysis failed.
|
||||
bool l2_valid;
|
||||
|
||||
// These are computed from Layer 2 data. These fields are only valid if
|
||||
// Layer2Valid() returns true.
|
||||
// l2_valid returns true.
|
||||
|
||||
/**
|
||||
* Layer 2 header size. Valid iff Layer2Valid() returns true.
|
||||
* Layer 2 header size. Valid iff l2_valid is true.
|
||||
*/
|
||||
uint32_t hdr_size;
|
||||
|
||||
/**
|
||||
* Layer 3 protocol identified (if any). Valid iff Layer2Valid()
|
||||
* returns true.
|
||||
* Layer 3 protocol identified (if any). Valid iff l2_valid is true.
|
||||
*/
|
||||
Layer3Proto l3_proto;
|
||||
|
||||
/**
|
||||
* If layer 2 is Ethernet, innermost ethertype field. Valid iff
|
||||
* Layer2Valid() returns true.
|
||||
* l2_valid is true.
|
||||
*/
|
||||
uint32_t eth_type;
|
||||
|
||||
/**
|
||||
* Layer 2 source address. Valid iff Layer2Valid() returns true.
|
||||
* Layer 2 source address. Valid iff l2_valid is true.
|
||||
*/
|
||||
const u_char* l2_src;
|
||||
|
||||
/**
|
||||
* Layer 2 destination address. Valid iff Layer2Valid() returns
|
||||
* true.
|
||||
* Layer 2 destination address. Valid iff l2_valid is true.
|
||||
*/
|
||||
const u_char* l2_dst;
|
||||
|
||||
/**
|
||||
* (Outermost) VLAN tag if any, else 0. Valid iff Layer2Valid()
|
||||
* returns true.
|
||||
* (Outermost) VLAN tag if any, else 0. Valid iff l2_valid is true.
|
||||
*/
|
||||
uint32_t vlan;
|
||||
|
||||
/**
|
||||
* (Innermost) VLAN tag if any, else 0. Valid iff Layer2Valid()
|
||||
* returns true.
|
||||
* (Innermost) VLAN tag if any, else 0. Valid iff l2_valid is true.
|
||||
*/
|
||||
uint32_t inner_vlan;
|
||||
|
||||
|
@ -224,22 +208,27 @@ public:
|
|||
*/
|
||||
bool l3_checksummed;
|
||||
|
||||
private:
|
||||
// Calculate layer 2 attributes.
|
||||
void ProcessLayer2();
|
||||
/**
|
||||
* Indicates whether the packet should be processed by zeek's
|
||||
* session analysis in NetSessions.
|
||||
*/
|
||||
bool session_analysis;
|
||||
|
||||
// Wrapper to generate a packet-level weird.
|
||||
/**
|
||||
* Indicates whether this packet should be recorded.
|
||||
*/
|
||||
mutable bool dump_packet;
|
||||
|
||||
// Wrapper to generate a packet-level weird. Has to be public for packet analyzers to use it.
|
||||
void Weird(const char* name);
|
||||
|
||||
private:
|
||||
// Renders an MAC address into its ASCII representation.
|
||||
ValPtr FmtEUI48(const u_char* mac) const;
|
||||
|
||||
// True if we need to delete associated packet memory upon
|
||||
// destruction.
|
||||
bool copy;
|
||||
|
||||
// True if L2 processing succeeded.
|
||||
bool l2_valid;
|
||||
};
|
||||
|
||||
} // namespace zeek
|
||||
|
|
|
@ -53,11 +53,6 @@ const char* PktDumper::ErrorMsg() const
|
|||
return errmsg.size() ? errmsg.c_str() : nullptr;
|
||||
}
|
||||
|
||||
int PktDumper::HdrSize() const
|
||||
{
|
||||
return is_open ? props.hdr_size : -1;
|
||||
}
|
||||
|
||||
void PktDumper::Opened(const Properties& arg_props)
|
||||
{
|
||||
is_open = true;
|
||||
|
|
|
@ -50,11 +50,6 @@ public:
|
|||
*/
|
||||
const char* ErrorMsg() const;
|
||||
|
||||
/**
|
||||
* Returns the size of the link-layer headers with this dumper.
|
||||
*/
|
||||
int HdrSize() const;
|
||||
|
||||
// PktDumper interface for derived classes to implement.
|
||||
|
||||
/**
|
||||
|
@ -97,7 +92,6 @@ protected:
|
|||
*/
|
||||
struct Properties {
|
||||
std::string path;
|
||||
int hdr_size;
|
||||
double open_time;
|
||||
};
|
||||
|
||||
|
|
|
@ -90,16 +90,6 @@ double PktSrc::CurrentPacketWallClock()
|
|||
|
||||
void PktSrc::Opened(const Properties& arg_props)
|
||||
{
|
||||
if ( Packet::GetLinkHeaderSize(arg_props.link_type) < 0 )
|
||||
{
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"unknown data link type 0x%x", arg_props.link_type);
|
||||
Error(buf);
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
props = arg_props;
|
||||
SetClosed(false);
|
||||
|
||||
|
@ -199,7 +189,7 @@ void PktSrc::Process()
|
|||
if ( ! ExtractNextPacketInternal() )
|
||||
return;
|
||||
|
||||
if ( current_packet.Layer2Valid() )
|
||||
if ( current_packet.l2_valid )
|
||||
{
|
||||
if ( run_state::pseudo_realtime )
|
||||
{
|
||||
|
|
|
@ -82,7 +82,6 @@ void PcapDumper::Open()
|
|||
}
|
||||
|
||||
props.open_time = run_state::network_time;
|
||||
props.hdr_size = Packet::GetLinkHeaderSize(pcap_datalink(pd));
|
||||
Opened(props);
|
||||
}
|
||||
|
||||
|
|
135
src/packet_analysis/Analyzer.cc
Normal file
135
src/packet_analysis/Analyzer.cc
Normal file
|
@ -0,0 +1,135 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "Analyzer.h"
|
||||
|
||||
#include "Dict.h"
|
||||
#include "DebugLogger.h"
|
||||
|
||||
namespace zeek::packet_analysis {
|
||||
|
||||
Analyzer::Analyzer(std::string name)
|
||||
{
|
||||
Tag t = packet_mgr->GetComponentTag(name);
|
||||
|
||||
if ( ! t )
|
||||
reporter->InternalError("unknown packet_analysis name %s", name.c_str());
|
||||
|
||||
Init(t);
|
||||
}
|
||||
|
||||
Analyzer::Analyzer(const Tag& tag)
|
||||
{
|
||||
Init(tag);
|
||||
}
|
||||
|
||||
void Analyzer::Init(const Tag& _tag)
|
||||
{
|
||||
tag = _tag;
|
||||
}
|
||||
|
||||
void Analyzer::Initialize()
|
||||
{
|
||||
default_analyzer = LoadAnalyzer("default_analyzer");
|
||||
|
||||
// Create dispatcher based on configuration
|
||||
auto& mapping_id = zeek::id::find(GetModuleName() + "dispatch_map");
|
||||
if ( ! mapping_id )
|
||||
return;
|
||||
|
||||
auto mapping_val = mapping_id->GetVal()->AsTableVal();
|
||||
auto mapping_tbl = mapping_val->AsTable();
|
||||
auto c = mapping_tbl->InitForIteration();
|
||||
|
||||
zeek::detail::HashKey* k = nullptr;
|
||||
TableEntryVal* v;
|
||||
while ( (v = mapping_tbl->NextEntry(k, c)) )
|
||||
{
|
||||
auto key = mapping_val->RecreateIndex(*k);
|
||||
delete k;
|
||||
|
||||
auto identifier = key->Idx(0)->AsCount();
|
||||
auto config_entry_val = v->GetVal()->AsRecordVal();
|
||||
|
||||
auto mapped_tag = config_entry_val->GetField("analyzer")->AsEnumVal();
|
||||
auto mapped_analyzer = packet_mgr->GetAnalyzer(mapped_tag);
|
||||
|
||||
dispatcher.Register(identifier, std::move(mapped_analyzer));
|
||||
}
|
||||
}
|
||||
|
||||
zeek::packet_analysis::AnalyzerPtr Analyzer::LoadAnalyzer(const std::string &name)
|
||||
{
|
||||
auto& analyzer = zeek::id::find(GetModuleName() + name);
|
||||
if ( ! analyzer )
|
||||
return nullptr;
|
||||
|
||||
auto& analyzer_val = analyzer->GetVal();
|
||||
if ( ! analyzer_val )
|
||||
return nullptr;
|
||||
|
||||
return packet_mgr->GetAnalyzer(analyzer_val->AsEnumVal());
|
||||
}
|
||||
|
||||
const Tag Analyzer::GetAnalyzerTag() const
|
||||
{
|
||||
assert(tag);
|
||||
return tag;
|
||||
}
|
||||
|
||||
const char* Analyzer::GetAnalyzerName() const
|
||||
{
|
||||
assert(tag);
|
||||
return packet_mgr->GetComponentName(tag).c_str();
|
||||
}
|
||||
|
||||
bool Analyzer::IsAnalyzer(const char* name)
|
||||
{
|
||||
assert(tag);
|
||||
return packet_mgr->GetComponentName(tag) == name;
|
||||
}
|
||||
|
||||
AnalyzerPtr Analyzer::Lookup(uint32_t identifier) const
|
||||
{
|
||||
return dispatcher.Lookup(identifier);
|
||||
}
|
||||
|
||||
bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet,
|
||||
uint32_t identifier) const
|
||||
{
|
||||
auto inner_analyzer = Lookup(identifier);
|
||||
if ( ! inner_analyzer )
|
||||
inner_analyzer = default_analyzer;
|
||||
|
||||
if ( inner_analyzer == nullptr )
|
||||
{
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s failed, could not find analyzer for identifier %#x.",
|
||||
GetAnalyzerName(), identifier);
|
||||
packet->Weird("no_suitable_analyzer_found");
|
||||
return false;
|
||||
}
|
||||
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.",
|
||||
GetAnalyzerName(), identifier);
|
||||
return inner_analyzer->AnalyzePacket(len, data, packet);
|
||||
}
|
||||
|
||||
bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet) const
|
||||
{
|
||||
if ( default_analyzer )
|
||||
return default_analyzer->AnalyzePacket(len, data, packet);
|
||||
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s stopped, no default analyzer available.",
|
||||
GetAnalyzerName());
|
||||
packet->Weird("no_suitable_analyzer_found");
|
||||
return true;
|
||||
}
|
||||
|
||||
void Analyzer::DumpDebug() const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Dispatcher for %s", this->GetAnalyzerName());
|
||||
dispatcher.DumpDebug();
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
150
src/packet_analysis/Analyzer.h
Normal file
150
src/packet_analysis/Analyzer.h
Normal file
|
@ -0,0 +1,150 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
#pragma once
|
||||
|
||||
#include "Manager.h"
|
||||
#include "Tag.h"
|
||||
#include <iosource/Packet.h>
|
||||
|
||||
namespace zeek::packet_analysis {
|
||||
|
||||
/**
|
||||
* Main packet analyzer interface.
|
||||
*/
|
||||
class Analyzer {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name The name for the type of analyzer. The name must match
|
||||
* the one the corresponding Component registers.
|
||||
*/
|
||||
explicit Analyzer(std::string name);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param tag The tag for the type of analyzer. The tag must map to
|
||||
* the name the corresponding Component registers.
|
||||
*/
|
||||
explicit Analyzer(const Tag& tag);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~Analyzer() = default;
|
||||
|
||||
/**
|
||||
* Initialize the analyzer. This method is called after the configuration
|
||||
* was read. Derived classes can override this method to implement custom
|
||||
* initialization.
|
||||
* When overriding this methods, always make sure to call the base-class
|
||||
* version to ensure proper initialization.
|
||||
*/
|
||||
virtual void Initialize();
|
||||
|
||||
/**
|
||||
* Returns the tag associated with the analyzer's type.
|
||||
*/
|
||||
const Tag GetAnalyzerTag() const;
|
||||
|
||||
/**
|
||||
* Returns a textual description of the analyzer's type. This is
|
||||
* what's passed to the constructor and usually corresponds to the
|
||||
* protocol name, e.g., "ARP".
|
||||
*/
|
||||
const char* GetAnalyzerName() const;
|
||||
|
||||
/**
|
||||
* Returns true if this analyzer's type matches the name passes in.
|
||||
* This is shortcut for comparing GetAnalyzerName() with the given
|
||||
* name.
|
||||
*
|
||||
* @param name The name to check.
|
||||
*/
|
||||
bool IsAnalyzer(const char* name);
|
||||
|
||||
/**
|
||||
* Analyzes the given packet. A common case is that the analyzed protocol
|
||||
* encapsulates another protocol, which can be determined by an identifier
|
||||
* in the header. In this case, derived classes may use ForwardPacket() to
|
||||
* forward the payload to the corresponding analyzer.
|
||||
*
|
||||
* @param len The number of bytes passed in.
|
||||
* @param data Pointer to the input to process.
|
||||
* @param packet Object that maintains the packet's meta data.
|
||||
*
|
||||
* @return false if the analysis failed, else true.
|
||||
*/
|
||||
virtual bool AnalyzePacket(size_t len, const uint8_t* data,
|
||||
Packet* packet) = 0;
|
||||
|
||||
/**
|
||||
* Dumps out debug information to the \c analyzer debug stream.
|
||||
*/
|
||||
void DumpDebug() const;
|
||||
|
||||
protected:
|
||||
friend class Manager;
|
||||
|
||||
/**
|
||||
* Looks up the analyzer for the encapsulated protocol based on the given
|
||||
* identifier.
|
||||
*
|
||||
* @param identifier Identifier for the encapsulated protocol.
|
||||
* @return The analyzer registered for the given identifier. Returns a
|
||||
* nullptr if no analyzer is registered.
|
||||
*/
|
||||
AnalyzerPtr Lookup(uint32_t identifier) const;
|
||||
|
||||
/**
|
||||
* Returns an analyzer based on a script-land definition.
|
||||
*
|
||||
* @param name The script-land identifier for a PacketAnalyzer::Tag value.
|
||||
* @return The defined analyzer if available, else nullptr.
|
||||
*/
|
||||
AnalyzerPtr LoadAnalyzer(const std::string& name);
|
||||
|
||||
/**
|
||||
* Returns the module name corresponding to the analyzer, i.e. its script-land
|
||||
* namespace. Configuration values for the analyzer are expected in this module.
|
||||
* @return Analyzer's module name.
|
||||
*/
|
||||
std::string GetModuleName() const {
|
||||
return util::fmt("PacketAnalyzer::%s::", GetAnalyzerName());
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggers analysis of the encapsulated packet. The encapsulated protocol
|
||||
* is determined using the given identifier.
|
||||
*
|
||||
* @param packet The packet to analyze.
|
||||
* @param data Reference to the payload pointer into the raw packet.
|
||||
* @param identifier The identifier of the encapsulated protocol.
|
||||
*
|
||||
* @return false if the analysis failed, else true.
|
||||
*/
|
||||
bool ForwardPacket(size_t len, const uint8_t* data, Packet* packet,
|
||||
uint32_t identifier) const;
|
||||
|
||||
/**
|
||||
* Triggers default analysis of the encapsulated packet if the default analyzer
|
||||
* is set.
|
||||
*
|
||||
* @param packet The packet to analyze.
|
||||
* @param data Reference to the payload pointer into the raw packet.
|
||||
*
|
||||
* @return false if the analysis failed, else true.
|
||||
*/
|
||||
bool ForwardPacket(size_t len, const uint8_t* data, Packet* packet) const;
|
||||
|
||||
private:
|
||||
Tag tag;
|
||||
Dispatcher dispatcher;
|
||||
AnalyzerPtr default_analyzer = nullptr;
|
||||
|
||||
void Init(const Tag& tag);
|
||||
};
|
||||
|
||||
using AnalyzerPtr = std::shared_ptr<Analyzer>;
|
||||
|
||||
}
|
20
src/packet_analysis/CMakeLists.txt
Normal file
20
src/packet_analysis/CMakeLists.txt
Normal file
|
@ -0,0 +1,20 @@
|
|||
|
||||
include(ZeekSubdir)
|
||||
|
||||
include_directories(BEFORE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
add_subdirectory(protocol)
|
||||
|
||||
set(packet_analysis_SRCS
|
||||
Analyzer.cc
|
||||
Dispatcher.cc
|
||||
Manager.cc
|
||||
Component.cc
|
||||
Tag.cc
|
||||
)
|
||||
|
||||
bro_add_subdir_library(packet_analysis ${packet_analysis_SRCS})
|
||||
add_dependencies(bro_packet_analysis generate_outputs)
|
29
src/packet_analysis/Component.cc
Normal file
29
src/packet_analysis/Component.cc
Normal file
|
@ -0,0 +1,29 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "Component.h"
|
||||
#include "Desc.h"
|
||||
#include "Manager.h"
|
||||
|
||||
using namespace zeek::packet_analysis;
|
||||
|
||||
Component::Component(const std::string& name, factory_callback arg_factory, Tag::subtype_t arg_subtype)
|
||||
: plugin::Component(plugin::component::PACKET_ANALYZER, name),
|
||||
plugin::TaggedComponent<packet_analysis::Tag>(arg_subtype)
|
||||
{
|
||||
factory = arg_factory;
|
||||
}
|
||||
|
||||
void Component::Initialize()
|
||||
{
|
||||
InitializeTag();
|
||||
packet_mgr->RegisterComponent(this, "ANALYZER_");
|
||||
}
|
||||
|
||||
void Component::DoDescribe(ODesc* d) const
|
||||
{
|
||||
if ( factory )
|
||||
{
|
||||
d->Add("ANALYZER_");
|
||||
d->Add(CanonicalName());
|
||||
}
|
||||
}
|
47
src/packet_analysis/Component.h
Normal file
47
src/packet_analysis/Component.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "zeek-config.h"
|
||||
#include "util.h"
|
||||
#include "Tag.h"
|
||||
|
||||
#include "plugin/Component.h"
|
||||
#include "plugin/TaggedComponent.h"
|
||||
|
||||
namespace zeek::packet_analysis {
|
||||
|
||||
class Analyzer;
|
||||
using AnalyzerPtr = std::shared_ptr<Analyzer>;
|
||||
|
||||
class Component : public plugin::Component,
|
||||
public plugin::TaggedComponent<packet_analysis::Tag> {
|
||||
public:
|
||||
typedef AnalyzerPtr (*factory_callback)();
|
||||
|
||||
Component(const std::string& name, factory_callback factory, Tag::subtype_t subtype = 0);
|
||||
~Component() override = default;
|
||||
|
||||
/**
|
||||
* Initialization function. This function has to be called before any
|
||||
* plugin component functionality is used; it is used to add the
|
||||
* plugin component to the list of components and to initialize tags
|
||||
*/
|
||||
void Initialize() override;
|
||||
|
||||
/**
|
||||
* Returns the analyzer's factory function.
|
||||
*/
|
||||
factory_callback Factory() const { return factory; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Overriden from plugin::Component.
|
||||
*/
|
||||
void DoDescribe(ODesc* d) const override;
|
||||
|
||||
private:
|
||||
factory_callback factory; // The analyzer's factory callback.
|
||||
};
|
||||
|
||||
}
|
97
src/packet_analysis/Dispatcher.cc
Normal file
97
src/packet_analysis/Dispatcher.cc
Normal file
|
@ -0,0 +1,97 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "Dispatcher.h"
|
||||
#include "Analyzer.h"
|
||||
#include "Reporter.h"
|
||||
#include "DebugLogger.h"
|
||||
|
||||
namespace zeek::packet_analysis {
|
||||
|
||||
Dispatcher::~Dispatcher()
|
||||
{
|
||||
FreeValues();
|
||||
}
|
||||
|
||||
void Dispatcher::Register(uint32_t identifier, AnalyzerPtr analyzer)
|
||||
{
|
||||
// If the table has size 1 and the entry is nullptr, there was nothing added yet. Just add it.
|
||||
if ( table.size() == 1 && table[0] == nullptr )
|
||||
{
|
||||
table[0] = std::move(analyzer);
|
||||
lowest_identifier = identifier;
|
||||
return;
|
||||
}
|
||||
|
||||
// If highestIdentifier == identifier, overwrite would happen -> no check needed, will return false
|
||||
if ( GetHighestIdentifier() < identifier )
|
||||
{
|
||||
table.resize(table.size() + (identifier - GetHighestIdentifier()), nullptr);
|
||||
}
|
||||
else if ( identifier < lowest_identifier )
|
||||
{
|
||||
// Lower than the lowest registered identifier. Shift up by lowerBound - identifier
|
||||
uint32_t distance = lowest_identifier - identifier;
|
||||
table.resize(table.size() + distance, nullptr);
|
||||
|
||||
// Shift values
|
||||
for ( ssize_t i = table.size() - 1; i >= 0; i-- )
|
||||
{
|
||||
if ( table[i] != nullptr )
|
||||
{
|
||||
table.at(i + distance) = std::move(table.at(i));
|
||||
table.at(i) = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
lowest_identifier = identifier;
|
||||
}
|
||||
|
||||
int64_t index = identifier - lowest_identifier;
|
||||
if ( table[index] != nullptr )
|
||||
reporter->InternalWarning("Overwriting packet analyzer mapping %#8" PRIx64 " => %s with %s",
|
||||
index+lowest_identifier, table[index]->GetAnalyzerName(), analyzer->GetAnalyzerName());
|
||||
table[index] = std::move(analyzer);
|
||||
}
|
||||
|
||||
AnalyzerPtr Dispatcher::Lookup(uint32_t identifier) const
|
||||
{
|
||||
int64_t index = identifier - lowest_identifier;
|
||||
if ( index >= 0 && index < static_cast<int64_t>(table.size()) && table[index] != nullptr )
|
||||
return table[index];
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t Dispatcher::Count() const
|
||||
{
|
||||
return std::count_if(table.begin(), table.end(), [](AnalyzerPtr a) { return a != nullptr; });
|
||||
}
|
||||
|
||||
void Dispatcher::Clear()
|
||||
{
|
||||
FreeValues();
|
||||
table.clear();
|
||||
}
|
||||
|
||||
void Dispatcher::FreeValues()
|
||||
{
|
||||
for ( auto& current : table )
|
||||
current = nullptr;
|
||||
}
|
||||
|
||||
void Dispatcher::DumpDebug() const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Dispatcher elements (used/total): %lu/%lu", Count(), table.size());
|
||||
for ( size_t i = 0; i < table.size(); i++ )
|
||||
{
|
||||
if ( table[i] != nullptr )
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "%#8lx => %s",
|
||||
i+lowest_identifier, table[i]->GetAnalyzerName());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
68
src/packet_analysis/Dispatcher.h
Normal file
68
src/packet_analysis/Dispatcher.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace zeek::packet_analysis {
|
||||
|
||||
class Analyzer; // Forward declaration for Value
|
||||
using AnalyzerPtr = std::shared_ptr<zeek::packet_analysis::Analyzer>;
|
||||
|
||||
/**
|
||||
* The Dispatcher class manages identifier-to-analyzer mappings.
|
||||
*/
|
||||
class Dispatcher {
|
||||
public:
|
||||
Dispatcher() : table(std::vector<AnalyzerPtr>(1, nullptr)) { };
|
||||
~Dispatcher();
|
||||
|
||||
/**
|
||||
* Register an analyzer for a given identifier.
|
||||
*
|
||||
* @param identifier The identifier.
|
||||
* @param analyzer The analyzer to register.
|
||||
*/
|
||||
void Register(uint32_t identifier, AnalyzerPtr analyzer);
|
||||
|
||||
/**
|
||||
* Looks up the analyzer for an identifier.
|
||||
*
|
||||
* @param identifier The identifier to look up.
|
||||
* @return The analyzer registered for the given identifier. Returns a
|
||||
* nullptr if no analyzer is registered.
|
||||
*/
|
||||
AnalyzerPtr Lookup(uint32_t identifier) const;
|
||||
|
||||
/**
|
||||
* Returns the number of registered analyzers.
|
||||
* @return Number of registered analyzers.
|
||||
*/
|
||||
size_t Count() const;
|
||||
|
||||
/**
|
||||
* Removes all mappings from the dispatcher.
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
/**
|
||||
* Dumps out the data structure to the \c analyzer debug stream.
|
||||
*/
|
||||
void DumpDebug() const;
|
||||
|
||||
private:
|
||||
uint32_t lowest_identifier = 0;
|
||||
std::vector<AnalyzerPtr> table;
|
||||
|
||||
void FreeValues();
|
||||
|
||||
inline uint32_t GetHighestIdentifier() const
|
||||
{
|
||||
return lowest_identifier + table.size() - 1;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
114
src/packet_analysis/Manager.cc
Normal file
114
src/packet_analysis/Manager.cc
Normal file
|
@ -0,0 +1,114 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "Manager.h"
|
||||
|
||||
#include "Analyzer.h"
|
||||
#include "Dispatcher.h"
|
||||
|
||||
using namespace zeek::packet_analysis;
|
||||
|
||||
Manager::Manager()
|
||||
: plugin::ComponentManager<packet_analysis::Tag, packet_analysis::Component>("PacketAnalyzer", "Tag")
|
||||
{
|
||||
}
|
||||
|
||||
void Manager::InitPostScript()
|
||||
{
|
||||
// Instantiate objects for all available analyzers
|
||||
for ( const auto& analyzerComponent : GetComponents() )
|
||||
{
|
||||
if ( AnalyzerPtr newAnalyzer = InstantiateAnalyzer(analyzerComponent->Tag()) )
|
||||
analyzers.emplace(analyzerComponent->Name(), newAnalyzer);
|
||||
}
|
||||
|
||||
// Initialize all analyzers
|
||||
for ( auto& [name, analyzer] : analyzers )
|
||||
analyzer->Initialize();
|
||||
|
||||
root_analyzer = analyzers["Root"];
|
||||
}
|
||||
|
||||
void Manager::Done()
|
||||
{
|
||||
}
|
||||
|
||||
void Manager::DumpDebug()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Available packet analyzers after zeek_init():");
|
||||
for ( auto& current : GetComponents() )
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, " %s", current->Name().c_str());
|
||||
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Packet analyzer debug information:");
|
||||
for ( auto& [name, analyzer] : analyzers )
|
||||
analyzer->DumpDebug();
|
||||
#endif
|
||||
}
|
||||
|
||||
AnalyzerPtr Manager::GetAnalyzer(EnumVal *val)
|
||||
{
|
||||
auto analyzer_comp = Lookup(val);
|
||||
if ( ! analyzer_comp )
|
||||
return nullptr;
|
||||
|
||||
return GetAnalyzer(analyzer_comp->Name());
|
||||
}
|
||||
|
||||
AnalyzerPtr Manager::GetAnalyzer(const std::string& name)
|
||||
{
|
||||
auto analyzer_it = analyzers.find(name);
|
||||
if ( analyzer_it == analyzers.end() )
|
||||
return nullptr;
|
||||
|
||||
return analyzer_it->second;
|
||||
}
|
||||
|
||||
void Manager::ProcessPacket(Packet* packet)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
static size_t counter = 0;
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analyzing packet %ld, ts=%.3f...", ++counter, packet->time);
|
||||
#endif
|
||||
// Start packet analysis
|
||||
packet->l2_valid = root_analyzer->ForwardPacket(packet->cap_len, packet->data,
|
||||
packet, packet->link_type);
|
||||
}
|
||||
|
||||
AnalyzerPtr Manager::InstantiateAnalyzer(const Tag& tag)
|
||||
{
|
||||
Component* c = Lookup(tag);
|
||||
|
||||
if ( ! c )
|
||||
{
|
||||
reporter->InternalWarning("request to instantiate unknown packet_analysis");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ( ! c->Factory() )
|
||||
{
|
||||
reporter->InternalWarning("analyzer %s cannot be instantiated dynamically", GetComponentName(tag).c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AnalyzerPtr a = c->Factory()();
|
||||
|
||||
if ( ! a )
|
||||
{
|
||||
reporter->InternalWarning("analyzer instantiation failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ( tag != a->GetAnalyzerTag() )
|
||||
{
|
||||
reporter->InternalError("Mismatch of requested analyzer %s and instantiated analyzer %s. This usually means that the plugin author made a mistake.",
|
||||
GetComponentName(tag).c_str(), GetComponentName(a->GetAnalyzerTag()).c_str());
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
AnalyzerPtr Manager::InstantiateAnalyzer(const std::string& name)
|
||||
{
|
||||
Tag tag = GetComponentTag(name);
|
||||
return tag ? InstantiateAnalyzer(tag) : nullptr;
|
||||
}
|
98
src/packet_analysis/Manager.h
Normal file
98
src/packet_analysis/Manager.h
Normal file
|
@ -0,0 +1,98 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Tag.h"
|
||||
#include "Component.h"
|
||||
#include "plugin/ComponentManager.h"
|
||||
#include "iosource/Packet.h"
|
||||
#include "Dispatcher.h"
|
||||
|
||||
namespace zeek::packet_analysis {
|
||||
|
||||
class Analyzer;
|
||||
using AnalyzerPtr = std::shared_ptr<Analyzer>;
|
||||
|
||||
class Manager : public plugin::ComponentManager<Tag, Component> {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
Manager();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~Manager() = default;
|
||||
|
||||
/**
|
||||
* Second-stage initialization of the manager. This is called late
|
||||
* during Zeek's initialization after any scripts are processed.
|
||||
*/
|
||||
void InitPostScript();
|
||||
|
||||
/**
|
||||
* Finished the manager's operations.
|
||||
*/
|
||||
void Done();
|
||||
|
||||
/**
|
||||
* Dumps out the state of all registered analyzers to the \c analyzer
|
||||
* debug stream. Should be called only after any \c zeek_init events
|
||||
* have executed to ensure that any of their changes are applied.
|
||||
*/
|
||||
void DumpDebug(); // Called after zeek_init() events.
|
||||
|
||||
/**
|
||||
* Looks up an analyzer instance.
|
||||
*
|
||||
* @param val The analyzer's tag value.
|
||||
*
|
||||
* @return The analyzer instance or nullptr if no instance is found.
|
||||
*/
|
||||
AnalyzerPtr GetAnalyzer(EnumVal *val);
|
||||
|
||||
/**
|
||||
* Looks up an analyzer instance.
|
||||
*
|
||||
* @param name The name of the analyzer.
|
||||
*
|
||||
* @return The analyzer instance or nullptr if no instance is found.
|
||||
*/
|
||||
AnalyzerPtr GetAnalyzer(const std::string& name);
|
||||
|
||||
/**
|
||||
* Processes a packet by applying the configured packet analyzers.
|
||||
*
|
||||
* @param packet The packet to process.
|
||||
*/
|
||||
void ProcessPacket(Packet* packet);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Instantiates a new analyzer instance.
|
||||
*
|
||||
* @param tag The analyzer's tag.
|
||||
*
|
||||
* @return The new analyzer instance. Returns null if tag is invalid, the
|
||||
* requested analyzer is disabled, or the analyzer can't be instantiated.
|
||||
*/
|
||||
AnalyzerPtr InstantiateAnalyzer(const Tag& tag);
|
||||
|
||||
/**
|
||||
* Instantiates a new analyzer.
|
||||
*
|
||||
* @param name The name of the analyzer.
|
||||
*
|
||||
* @return The new analyzer instance. Returns null if the name is not known
|
||||
* or if the requested analyzer that is disabled.
|
||||
*/
|
||||
AnalyzerPtr InstantiateAnalyzer(const std::string& name);
|
||||
|
||||
std::map<std::string, AnalyzerPtr> analyzers;
|
||||
AnalyzerPtr root_analyzer = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
extern zeek::packet_analysis::Manager* packet_mgr;
|
31
src/packet_analysis/Tag.cc
Normal file
31
src/packet_analysis/Tag.cc
Normal file
|
@ -0,0 +1,31 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "Tag.h"
|
||||
#include "Manager.h"
|
||||
|
||||
namespace zeek::packet_analysis {
|
||||
|
||||
Tag Tag::Error;
|
||||
|
||||
Tag::Tag(type_t type, subtype_t subtype)
|
||||
: zeek::Tag(packet_mgr->GetTagType(), type, subtype)
|
||||
{
|
||||
}
|
||||
|
||||
Tag& Tag::operator=(const Tag& other)
|
||||
{
|
||||
zeek::Tag::operator=(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const IntrusivePtr<EnumVal>& Tag::AsVal() const
|
||||
{
|
||||
return zeek::Tag::AsVal(packet_mgr->GetTagType());
|
||||
}
|
||||
|
||||
Tag::Tag(IntrusivePtr<EnumVal> val)
|
||||
: zeek::Tag(std::move(val))
|
||||
{
|
||||
}
|
||||
|
||||
}
|
110
src/packet_analysis/Tag.h
Normal file
110
src/packet_analysis/Tag.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "zeek-config.h"
|
||||
#include "../Tag.h"
|
||||
|
||||
namespace zeek::plugin {
|
||||
template <class T> class TaggedComponent;
|
||||
template <class T, class C> class ComponentManager;
|
||||
}
|
||||
|
||||
namespace zeek::packet_analysis {
|
||||
|
||||
class Manager;
|
||||
class Component;
|
||||
|
||||
/**
|
||||
* Class to identify a protocol analyzer type.
|
||||
*/
|
||||
class Tag : public zeek::Tag {
|
||||
public:
|
||||
/*
|
||||
* Copy constructor.
|
||||
*/
|
||||
Tag(const Tag& other) : zeek::Tag(other) { }
|
||||
|
||||
/**
|
||||
* Default constructor. This initializes the tag with an error value
|
||||
* that will make \c operator \c bool return false.
|
||||
*/
|
||||
Tag() : zeek::Tag() { }
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~Tag() = default;
|
||||
|
||||
/**
|
||||
* Returns false if the tag represents an error value rather than a
|
||||
* legal analyzer type.
|
||||
*/
|
||||
explicit operator bool() const { return *this != Tag(); }
|
||||
|
||||
/**
|
||||
* Assignment operator.
|
||||
*/
|
||||
Tag& operator=(const Tag& other);
|
||||
|
||||
/**
|
||||
* Compares two tags for equality.
|
||||
*/
|
||||
bool operator==(const Tag& other) const
|
||||
{
|
||||
return zeek::Tag::operator==(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two tags for inequality.
|
||||
*/
|
||||
bool operator!=(const Tag& other) const
|
||||
{
|
||||
return zeek::Tag::operator!=(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two tags for less-than relationship.
|
||||
*/
|
||||
bool operator<(const Tag& other) const
|
||||
{
|
||||
return zeek::Tag::operator<(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the \c Analyzer::Tag enum that corresponds to this tag.
|
||||
* The returned value does not have its ref-count increased.
|
||||
*
|
||||
* @param etype the script-layer enum type associated with the tag.
|
||||
*/
|
||||
const IntrusivePtr<EnumVal>& AsVal() const;
|
||||
|
||||
static Tag Error;
|
||||
|
||||
protected:
|
||||
|
||||
friend class packet_analysis::Manager;
|
||||
friend class plugin::ComponentManager<Tag, Component>;
|
||||
friend class plugin::TaggedComponent<Tag>;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param type The main type. Note that the \a zeek::packet_analysis::Manager
|
||||
* manages the value space internally, so noone else should assign any main
|
||||
* types.
|
||||
*
|
||||
* @param subtype The sub type, which is left to an analyzer for
|
||||
* interpretation. By default it's set to zero.
|
||||
*/
|
||||
explicit Tag(type_t type, subtype_t subtype = 0);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param val An enum value of script type \c Analyzer::Tag.
|
||||
*/
|
||||
explicit Tag(IntrusivePtr<EnumVal> val);
|
||||
};
|
||||
|
||||
}
|
19
src/packet_analysis/protocol/CMakeLists.txt
Normal file
19
src/packet_analysis/protocol/CMakeLists.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
add_subdirectory(root)
|
||||
add_subdirectory(skip)
|
||||
|
||||
add_subdirectory(null)
|
||||
add_subdirectory(ethernet)
|
||||
add_subdirectory(vlan)
|
||||
add_subdirectory(pppoe)
|
||||
add_subdirectory(ppp_serial)
|
||||
add_subdirectory(ieee802_11)
|
||||
add_subdirectory(ieee802_11_radio)
|
||||
add_subdirectory(fddi)
|
||||
add_subdirectory(nflog)
|
||||
add_subdirectory(mpls)
|
||||
add_subdirectory(linux_sll)
|
||||
|
||||
add_subdirectory(arp)
|
||||
add_subdirectory(ip)
|
||||
add_subdirectory(ipv4)
|
||||
add_subdirectory(ipv6)
|
229
src/packet_analysis/protocol/arp/ARP.cc
Normal file
229
src/packet_analysis/protocol/arp/ARP.cc
Normal file
|
@ -0,0 +1,229 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "ARP.h"
|
||||
#include "Event.h"
|
||||
|
||||
#include "events.bif.h"
|
||||
|
||||
#include "zeek-config.h"
|
||||
#ifdef HAVE_NET_ETHERNET_H
|
||||
#include <net/ethernet.h>
|
||||
#elif defined(HAVE_SYS_ETHERNET_H)
|
||||
#include <sys/ethernet.h>
|
||||
#elif defined(HAVE_NETINET_IF_ETHER_H)
|
||||
#include <netinet/if_ether.h>
|
||||
#elif defined(HAVE_NET_ETHERTYPES_H)
|
||||
#include <net/ethertypes.h>
|
||||
#endif
|
||||
|
||||
using namespace zeek::packet_analysis::ARP;
|
||||
|
||||
ARPAnalyzer::ARPAnalyzer()
|
||||
: zeek::packet_analysis::Analyzer("ARP")
|
||||
{
|
||||
}
|
||||
|
||||
// Argh! FreeBSD and Linux have almost completely different net/if_arp.h .
|
||||
// ... and on Solaris we are missing half of the ARPOP codes, so define
|
||||
// them here as necessary:
|
||||
|
||||
#ifndef ARPOP_REQUEST
|
||||
#define ARPOP_REQUEST 1 // ARP request.
|
||||
#endif
|
||||
#ifndef ARPOP_REPLY
|
||||
#define ARPOP_REPLY 2 // ARP reply.
|
||||
#endif
|
||||
#ifndef ARPOP_PREQUEST
|
||||
#define ARPOP_RREQUEST 3 // RARP request.
|
||||
#endif
|
||||
#ifndef ARPOP_RREPLY
|
||||
#define ARPOP_RREPLY 4 // RARP reply.
|
||||
#endif
|
||||
#ifndef ARPOP_InREQUEST
|
||||
#define ARPOP_InREQUEST 8 // InARP request.
|
||||
#endif
|
||||
#ifndef ARPOP_InREPLY
|
||||
#define ARPOP_InREPLY 9 // InARP reply.
|
||||
#endif
|
||||
#ifndef ARPOP_NAK
|
||||
#define ARPOP_NAK 10 // (ATM)ARP NAK.
|
||||
#endif
|
||||
|
||||
#ifndef ar_sha
|
||||
#define ar_sha(ap) ((caddr_t((ap)+1)) + 0)
|
||||
#endif
|
||||
|
||||
#ifndef ar_spa
|
||||
#define ar_spa(ap) ((caddr_t((ap)+1)) + (ap)->ar_hln)
|
||||
#endif
|
||||
|
||||
#ifndef ar_tha
|
||||
#define ar_tha(ap) ((caddr_t((ap)+1)) + (ap)->ar_hln + (ap)->ar_pln)
|
||||
#endif
|
||||
|
||||
#ifndef ar_tpa
|
||||
#define ar_tpa(ap) ((caddr_t((ap)+1)) + 2*(ap)->ar_hln + (ap)->ar_pln)
|
||||
#endif
|
||||
|
||||
#ifndef ARPOP_REVREQUEST
|
||||
#define ARPOP_REVREQUEST ARPOP_RREQUEST
|
||||
#endif
|
||||
|
||||
#ifndef ARPOP_REVREPLY
|
||||
#define ARPOP_REVREPLY ARPOP_RREPLY
|
||||
#endif
|
||||
|
||||
#ifndef ARPOP_INVREQUEST
|
||||
#define ARPOP_INVREQUEST ARPOP_InREQUEST
|
||||
#endif
|
||||
|
||||
#ifndef ARPOP_INVREPLY
|
||||
#define ARPOP_INVREPLY ARPOP_InREPLY
|
||||
#endif
|
||||
|
||||
bool ARPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
||||
{
|
||||
packet->l3_proto = L3_ARP;
|
||||
|
||||
// Check whether the header is complete.
|
||||
if ( sizeof(struct arp_pkthdr) > len )
|
||||
{
|
||||
packet->Weird("truncated_ARP");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check whether the packet is OK ("inspired" in tcpdump's print-arp.c).
|
||||
auto ah = (const struct arp_pkthdr*) data;
|
||||
|
||||
// Check the size.
|
||||
size_t min_length = (ar_tpa(ah) - (char*) data) + ah->ar_pln;
|
||||
if ( min_length > len )
|
||||
{
|
||||
packet->Weird("truncated_ARP");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the address description fields.
|
||||
switch ( ntohs(ah->ar_hrd) ) {
|
||||
case ARPHRD_ETHER:
|
||||
if ( ah->ar_hln != 6 )
|
||||
{
|
||||
// don't know how to handle the opcode
|
||||
BadARPEvent(ah, "corrupt-arp-header (hrd=%i, hln=%i)",
|
||||
ntohs(ah->ar_hrd), ah->ar_hln);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
// don't know how to proceed
|
||||
BadARPEvent(ah, "unknown-arp-hw-address (hrd=%i)", ntohs(ah->ar_hrd));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: We don't support IPv6 addresses.
|
||||
switch ( ntohs(ah->ar_pro) ) {
|
||||
case ETHERTYPE_IP:
|
||||
if ( ah->ar_pln != 4 )
|
||||
{
|
||||
// don't know how to handle the opcode
|
||||
BadARPEvent(ah,"corrupt-arp-header (pro=%i, pln=%i)",
|
||||
ntohs(ah->ar_pro), ah->ar_pln);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
// don't know how to proceed
|
||||
BadARPEvent(ah,"unknown-arp-proto-address (pro=%i)", ntohs(ah->ar_pro));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check MAC src address = ARP sender MAC address.
|
||||
if ( memcmp(packet->l2_src, ar_sha(ah), ah->ar_hln) != 0 )
|
||||
{
|
||||
BadARPEvent(ah, "weird-arp-sha");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the code is supported.
|
||||
switch ( ntohs(ah->ar_op) ) {
|
||||
case ARPOP_REQUEST:
|
||||
RequestReplyEvent(arp_request, packet->l2_src, packet->l2_dst,
|
||||
ar_spa(ah), ar_sha(ah), ar_tpa(ah), ar_tha(ah));
|
||||
break;
|
||||
|
||||
case ARPOP_REPLY:
|
||||
RequestReplyEvent(arp_reply, packet->l2_src, packet->l2_dst,
|
||||
ar_spa(ah), ar_sha(ah), ar_tpa(ah), ar_tha(ah));
|
||||
break;
|
||||
|
||||
case ARPOP_REVREQUEST:
|
||||
case ARPOP_REVREPLY:
|
||||
case ARPOP_INVREQUEST:
|
||||
case ARPOP_INVREPLY:
|
||||
{
|
||||
// don't know how to handle the opcode
|
||||
BadARPEvent(ah, "unimplemented-arp-opcode (%i)", ntohs(ah->ar_op));
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// invalid opcode
|
||||
BadARPEvent(ah, "invalid-arp-opcode (opcode=%i)", ntohs(ah->ar_op));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Leave packet analyzer land
|
||||
return true;
|
||||
}
|
||||
|
||||
zeek::AddrValPtr ARPAnalyzer::ToAddrVal(const void* addr)
|
||||
{
|
||||
//Note: We only handle IPv4 addresses.
|
||||
return zeek::make_intrusive<zeek::AddrVal>(*(const uint32_t*) addr);
|
||||
}
|
||||
|
||||
zeek::StringValPtr ARPAnalyzer::ToEthAddrStr(const u_char* addr)
|
||||
{
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
||||
return zeek::make_intrusive<zeek::StringVal>(buf);
|
||||
}
|
||||
|
||||
void ARPAnalyzer::BadARPEvent(const struct arp_pkthdr* hdr, const char* fmt, ...)
|
||||
{
|
||||
if ( ! bad_arp )
|
||||
return;
|
||||
|
||||
char msg[1024];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(msg, sizeof(msg), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
event_mgr.Enqueue(bad_arp,
|
||||
ToAddrVal(ar_spa(hdr)), ToEthAddrStr((const u_char*) ar_sha(hdr)),
|
||||
ToAddrVal(ar_tpa(hdr)), ToEthAddrStr((const u_char*) ar_tha(hdr)),
|
||||
zeek::make_intrusive<zeek::StringVal>(msg));
|
||||
}
|
||||
|
||||
void ARPAnalyzer::RequestReplyEvent(EventHandlerPtr e, const u_char *src, const u_char *dst,
|
||||
const char *spa, const char *sha, const char *tpa, const char *tha)
|
||||
{
|
||||
if ( ! e )
|
||||
return;
|
||||
|
||||
event_mgr.Enqueue(e, ToEthAddrStr(src), ToEthAddrStr(dst),
|
||||
ToAddrVal(spa), ToEthAddrStr((const u_char*) sha),
|
||||
ToAddrVal(tpa), ToEthAddrStr((const u_char*) tha));
|
||||
}
|
39
src/packet_analysis/protocol/arp/ARP.h
Normal file
39
src/packet_analysis/protocol/arp/ARP.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <packet_analysis/Analyzer.h>
|
||||
#include <packet_analysis/Component.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <net/if_arp.h>
|
||||
|
||||
#ifndef arp_pkthdr
|
||||
#define arp_pkthdr arphdr
|
||||
#endif
|
||||
|
||||
namespace zeek::packet_analysis::ARP {
|
||||
|
||||
class ARPAnalyzer : public Analyzer {
|
||||
public:
|
||||
ARPAnalyzer();
|
||||
~ARPAnalyzer() override = default;
|
||||
|
||||
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
|
||||
|
||||
static zeek::packet_analysis::AnalyzerPtr Instantiate()
|
||||
{
|
||||
return std::make_shared<ARPAnalyzer>();
|
||||
}
|
||||
|
||||
private:
|
||||
zeek::AddrValPtr ToAddrVal(const void* addr);
|
||||
zeek::StringValPtr ToEthAddrStr(const u_char* addr);
|
||||
|
||||
void BadARPEvent(const struct arp_pkthdr* hdr, const char* fmt, ...)
|
||||
__attribute__((format(printf, 3, 4)));
|
||||
void RequestReplyEvent(EventHandlerPtr e, const u_char* src, const u_char* dst,
|
||||
const char* spa, const char* sha, const char* tpa, const char* tha);
|
||||
};
|
||||
|
||||
}
|
9
src/packet_analysis/protocol/arp/CMakeLists.txt
Normal file
9
src/packet_analysis/protocol/arp/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
include(ZeekPlugin)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
zeek_plugin_begin(Zeek ARP)
|
||||
zeek_plugin_cc(ARP.cc Plugin.cc)
|
||||
zeek_plugin_bif(events.bif)
|
||||
zeek_plugin_end()
|
24
src/packet_analysis/protocol/arp/Plugin.cc
Normal file
24
src/packet_analysis/protocol/arp/Plugin.cc
Normal file
|
@ -0,0 +1,24 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "plugin/Plugin.h"
|
||||
#include "ARP.h"
|
||||
#include "packet_analysis/Component.h"
|
||||
|
||||
namespace zeek::plugin::Zeek_ARP {
|
||||
|
||||
class Plugin : public zeek::plugin::Plugin {
|
||||
public:
|
||||
zeek::plugin::Configuration Configure()
|
||||
{
|
||||
AddComponent(new zeek::packet_analysis::Component("ARP",
|
||||
zeek::packet_analysis::ARP::ARPAnalyzer::Instantiate));
|
||||
|
||||
zeek::plugin::Configuration config;
|
||||
config.name = "Zeek::ARP";
|
||||
config.description = "ARP packet analyzer";
|
||||
return config;
|
||||
}
|
||||
|
||||
} plugin;
|
||||
|
||||
}
|
8
src/packet_analysis/protocol/ethernet/CMakeLists.txt
Normal file
8
src/packet_analysis/protocol/ethernet/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
include(ZeekPlugin)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
zeek_plugin_begin(PacketAnalyzer Ethernet)
|
||||
zeek_plugin_cc(Ethernet.cc Plugin.cc)
|
||||
zeek_plugin_end()
|
92
src/packet_analysis/protocol/ethernet/Ethernet.cc
Normal file
92
src/packet_analysis/protocol/ethernet/Ethernet.cc
Normal file
|
@ -0,0 +1,92 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "Ethernet.h"
|
||||
#include "NetVar.h"
|
||||
#include "Manager.h"
|
||||
|
||||
using namespace zeek::packet_analysis::Ethernet;
|
||||
|
||||
EthernetAnalyzer::EthernetAnalyzer()
|
||||
: zeek::packet_analysis::Analyzer("Ethernet")
|
||||
{
|
||||
}
|
||||
|
||||
void EthernetAnalyzer::Initialize()
|
||||
{
|
||||
Analyzer::Initialize();
|
||||
|
||||
SNAPAnalyzer = LoadAnalyzer("snap_analyzer");
|
||||
NovellRawAnalyzer = LoadAnalyzer("novell_raw_analyzer");
|
||||
LLCAnalyzer = LoadAnalyzer("llc_analyzer");
|
||||
}
|
||||
|
||||
bool EthernetAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
||||
{
|
||||
// Make sure that we actually got an entire ethernet header before trying
|
||||
// to pull bytes out of it.
|
||||
if ( 16 >= len )
|
||||
{
|
||||
packet->Weird("truncated_ethernet_frame");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip past Cisco FabricPath to encapsulated ethernet frame.
|
||||
if ( data[12] == 0x89 && data[13] == 0x03 )
|
||||
{
|
||||
auto constexpr cfplen = 16;
|
||||
|
||||
if ( cfplen + 14 >= len )
|
||||
{
|
||||
packet->Weird("truncated_link_header_cfp");
|
||||
return false;
|
||||
}
|
||||
|
||||
data += cfplen;
|
||||
len -= cfplen;
|
||||
}
|
||||
|
||||
// Get protocol being carried from the ethernet frame.
|
||||
uint32_t protocol = (data[12] << 8) + data[13];
|
||||
|
||||
packet->eth_type = protocol;
|
||||
packet->l2_dst = data;
|
||||
packet->l2_src = data + 6;
|
||||
|
||||
// Ethernet II frames
|
||||
if ( protocol >= 1536 )
|
||||
return ForwardPacket(len - 14, data + 14, packet, protocol);
|
||||
|
||||
// Other ethernet frame types
|
||||
if ( protocol <= 1500 )
|
||||
{
|
||||
if ( 16 >= len )
|
||||
{
|
||||
packet->Weird("truncated_ethernet_frame");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Let specialized analyzers take over for non Ethernet II frames.
|
||||
// Note that pdata remains at the start of the ethernet frame.
|
||||
|
||||
AnalyzerPtr eth_analyzer = nullptr;
|
||||
|
||||
if ( data[14] == 0xAA && data[15] == 0xAA)
|
||||
// IEEE 802.2 SNAP
|
||||
eth_analyzer = SNAPAnalyzer;
|
||||
else if ( data[14] == 0xFF && data[15] == 0xFF)
|
||||
// Novell raw IEEE 802.3
|
||||
eth_analyzer = NovellRawAnalyzer;
|
||||
else
|
||||
// IEEE 802.2 LLC
|
||||
eth_analyzer = LLCAnalyzer;
|
||||
|
||||
if ( eth_analyzer )
|
||||
return eth_analyzer->AnalyzePacket(len, data, packet);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Undefined (1500 < EtherType < 1536)
|
||||
packet->Weird("undefined_ether_type");
|
||||
return false;
|
||||
}
|
29
src/packet_analysis/protocol/ethernet/Ethernet.h
Normal file
29
src/packet_analysis/protocol/ethernet/Ethernet.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <packet_analysis/Analyzer.h>
|
||||
#include <packet_analysis/Component.h>
|
||||
|
||||
namespace zeek::packet_analysis::Ethernet {
|
||||
|
||||
class EthernetAnalyzer : public Analyzer {
|
||||
public:
|
||||
EthernetAnalyzer();
|
||||
~EthernetAnalyzer() override = default;
|
||||
|
||||
void Initialize() override;
|
||||
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
|
||||
|
||||
static zeek::packet_analysis::AnalyzerPtr Instantiate()
|
||||
{
|
||||
return std::make_shared<EthernetAnalyzer>();
|
||||
}
|
||||
|
||||
private:
|
||||
AnalyzerPtr SNAPAnalyzer = nullptr;
|
||||
AnalyzerPtr NovellRawAnalyzer = nullptr;
|
||||
AnalyzerPtr LLCAnalyzer = nullptr;
|
||||
};
|
||||
|
||||
}
|
24
src/packet_analysis/protocol/ethernet/Plugin.cc
Normal file
24
src/packet_analysis/protocol/ethernet/Plugin.cc
Normal file
|
@ -0,0 +1,24 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "Ethernet.h"
|
||||
#include "plugin/Plugin.h"
|
||||
#include "packet_analysis/Component.h"
|
||||
|
||||
namespace zeek::plugin::Zeek_Ethernet {
|
||||
|
||||
class Plugin : public zeek::plugin::Plugin {
|
||||
public:
|
||||
zeek::plugin::Configuration Configure()
|
||||
{
|
||||
AddComponent(new zeek::packet_analysis::Component("Ethernet",
|
||||
zeek::packet_analysis::Ethernet::EthernetAnalyzer::Instantiate));
|
||||
|
||||
zeek::plugin::Configuration config;
|
||||
config.name = "Zeek::Ethernet";
|
||||
config.description = "Ethernet packet analyzer";
|
||||
return config;
|
||||
}
|
||||
|
||||
} plugin;
|
||||
|
||||
}
|
8
src/packet_analysis/protocol/fddi/CMakeLists.txt
Normal file
8
src/packet_analysis/protocol/fddi/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
include(ZeekPlugin)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
zeek_plugin_begin(PacketAnalyzer FDDI)
|
||||
zeek_plugin_cc(FDDI.cc Plugin.cc)
|
||||
zeek_plugin_end()
|
25
src/packet_analysis/protocol/fddi/FDDI.cc
Normal file
25
src/packet_analysis/protocol/fddi/FDDI.cc
Normal file
|
@ -0,0 +1,25 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "FDDI.h"
|
||||
#include "NetVar.h"
|
||||
|
||||
using namespace zeek::packet_analysis::FDDI;
|
||||
|
||||
FDDIAnalyzer::FDDIAnalyzer()
|
||||
: zeek::packet_analysis::Analyzer("FDDI")
|
||||
{
|
||||
}
|
||||
|
||||
bool FDDIAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
||||
{
|
||||
size_t hdr_size = 13 + 8; // FDDI header + LLC
|
||||
|
||||
if ( hdr_size >= len )
|
||||
{
|
||||
packet->Weird("FDDI_analyzer_failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// We just skip the header and hope for default analysis
|
||||
return ForwardPacket(len - hdr_size, data + hdr_size, packet);
|
||||
}
|
23
src/packet_analysis/protocol/fddi/FDDI.h
Normal file
23
src/packet_analysis/protocol/fddi/FDDI.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <packet_analysis/Analyzer.h>
|
||||
#include <packet_analysis/Component.h>
|
||||
|
||||
namespace zeek::packet_analysis::FDDI {
|
||||
|
||||
class FDDIAnalyzer : public zeek::packet_analysis::Analyzer {
|
||||
public:
|
||||
FDDIAnalyzer();
|
||||
~FDDIAnalyzer() override = default;
|
||||
|
||||
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
|
||||
|
||||
static zeek::packet_analysis::AnalyzerPtr Instantiate()
|
||||
{
|
||||
return std::make_shared<FDDIAnalyzer>();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
24
src/packet_analysis/protocol/fddi/Plugin.cc
Normal file
24
src/packet_analysis/protocol/fddi/Plugin.cc
Normal file
|
@ -0,0 +1,24 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "FDDI.h"
|
||||
#include "plugin/Plugin.h"
|
||||
#include "packet_analysis/Component.h"
|
||||
|
||||
namespace zeek::plugin::Zeek_FDDI {
|
||||
|
||||
class Plugin : public zeek::plugin::Plugin {
|
||||
public:
|
||||
zeek::plugin::Configuration Configure()
|
||||
{
|
||||
AddComponent(new zeek::packet_analysis::Component("FDDI",
|
||||
zeek::packet_analysis::FDDI::FDDIAnalyzer::Instantiate));
|
||||
|
||||
zeek::plugin::Configuration config;
|
||||
config.name = "Zeek::FDDI";
|
||||
config.description = "FDDI packet analyzer";
|
||||
return config;
|
||||
}
|
||||
|
||||
} plugin;
|
||||
|
||||
}
|
8
src/packet_analysis/protocol/ieee802_11/CMakeLists.txt
Normal file
8
src/packet_analysis/protocol/ieee802_11/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
include(ZeekPlugin)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
zeek_plugin_begin(PacketAnalyzer IEEE802_11)
|
||||
zeek_plugin_cc(IEEE802_11.cc Plugin.cc)
|
||||
zeek_plugin_end()
|
111
src/packet_analysis/protocol/ieee802_11/IEEE802_11.cc
Normal file
111
src/packet_analysis/protocol/ieee802_11/IEEE802_11.cc
Normal file
|
@ -0,0 +1,111 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "IEEE802_11.h"
|
||||
#include "NetVar.h"
|
||||
|
||||
using namespace zeek::packet_analysis::IEEE802_11;
|
||||
|
||||
IEEE802_11Analyzer::IEEE802_11Analyzer()
|
||||
: zeek::packet_analysis::Analyzer("IEEE802_11")
|
||||
{
|
||||
}
|
||||
|
||||
bool IEEE802_11Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
||||
{
|
||||
u_char len_80211 = 24; // minimal length of data frames
|
||||
|
||||
if ( len_80211 >= len )
|
||||
{
|
||||
packet->Weird("truncated_802_11_header");
|
||||
return false;
|
||||
}
|
||||
|
||||
u_char fc_80211 = data[0]; // Frame Control field
|
||||
|
||||
// Skip non-data frame types (management & control).
|
||||
if ( ! ((fc_80211 >> 2) & 0x02) )
|
||||
return false;
|
||||
|
||||
// Skip subtypes without data.
|
||||
if ( (fc_80211 >> 4) & 0x04 )
|
||||
return false;
|
||||
|
||||
// 'To DS' and 'From DS' flags set indicate use of the 4th
|
||||
// address field.
|
||||
if ( (data[1] & 0x03) == 0x03 )
|
||||
len_80211 += packet->L2_ADDR_LEN;
|
||||
|
||||
// Look for the QoS indicator bit.
|
||||
if ( (fc_80211 >> 4) & 0x08 )
|
||||
{
|
||||
// Skip in case of A-MSDU subframes indicated by QoS
|
||||
// control field.
|
||||
if ( data[len_80211] & 0x80 )
|
||||
return false;
|
||||
|
||||
len_80211 += 2;
|
||||
}
|
||||
|
||||
if ( len_80211 >= len )
|
||||
{
|
||||
packet->Weird("truncated_802_11_header");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine link-layer addresses based
|
||||
// on 'To DS' and 'From DS' flags
|
||||
switch ( data[1] & 0x03 )
|
||||
{
|
||||
case 0x00:
|
||||
packet->l2_src = data + 10;
|
||||
packet->l2_dst = data + 4;
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
packet->l2_src = data + 10;
|
||||
packet->l2_dst = data + 16;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
packet->l2_src = data + 16;
|
||||
packet->l2_dst = data + 4;
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
packet->l2_src = data + 24;
|
||||
packet->l2_dst = data + 16;
|
||||
break;
|
||||
}
|
||||
|
||||
// skip 802.11 data header
|
||||
data += len_80211;
|
||||
|
||||
len_80211 += 8;
|
||||
if ( len_80211 >= len )
|
||||
{
|
||||
packet->Weird("truncated_802_11_header");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the DSAP and SSAP are both SNAP and that the control
|
||||
// field indicates that this is an unnumbered frame.
|
||||
// The organization code (24bits) needs to also be zero to
|
||||
// indicate that this is encapsulated ethernet.
|
||||
if ( data[0] == 0xAA && data[1] == 0xAA && data[2] == 0x03 &&
|
||||
data[3] == 0 && data[4] == 0 && data[5] == 0 )
|
||||
{
|
||||
data += 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this is a logical link control frame without the
|
||||
// possibility of having a protocol we care about, we'll
|
||||
// just skip it for now.
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t protocol = (data[0] << 8) + data[1];
|
||||
data += 2;
|
||||
|
||||
return ForwardPacket(len - len_80211, data, packet, protocol);
|
||||
}
|
23
src/packet_analysis/protocol/ieee802_11/IEEE802_11.h
Normal file
23
src/packet_analysis/protocol/ieee802_11/IEEE802_11.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <packet_analysis/Analyzer.h>
|
||||
#include <packet_analysis/Component.h>
|
||||
|
||||
namespace zeek::packet_analysis::IEEE802_11 {
|
||||
|
||||
class IEEE802_11Analyzer : public Analyzer {
|
||||
public:
|
||||
IEEE802_11Analyzer();
|
||||
~IEEE802_11Analyzer() override = default;
|
||||
|
||||
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
|
||||
|
||||
static zeek::packet_analysis::AnalyzerPtr Instantiate()
|
||||
{
|
||||
return std::make_shared<IEEE802_11Analyzer>();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
24
src/packet_analysis/protocol/ieee802_11/Plugin.cc
Normal file
24
src/packet_analysis/protocol/ieee802_11/Plugin.cc
Normal file
|
@ -0,0 +1,24 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "IEEE802_11.h"
|
||||
#include "plugin/Plugin.h"
|
||||
#include "packet_analysis/Component.h"
|
||||
|
||||
namespace zeek::plugin::Zeek_IEEE802_11 {
|
||||
|
||||
class Plugin : public zeek::plugin::Plugin {
|
||||
public:
|
||||
zeek::plugin::Configuration Configure()
|
||||
{
|
||||
AddComponent(new zeek::packet_analysis::Component("IEEE802_11",
|
||||
zeek::packet_analysis::IEEE802_11::IEEE802_11Analyzer::Instantiate));
|
||||
|
||||
zeek::plugin::Configuration config;
|
||||
config.name = "Zeek::IEEE802_11";
|
||||
config.description = "IEEE 802.11 packet analyzer";
|
||||
return config;
|
||||
}
|
||||
|
||||
} plugin;
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
include(ZeekPlugin)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
zeek_plugin_begin(PacketAnalyzer IEEE802_11_Radio)
|
||||
zeek_plugin_cc(IEEE802_11_Radio.cc Plugin.cc)
|
||||
zeek_plugin_end()
|
|
@ -0,0 +1,33 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include <pcap.h>
|
||||
|
||||
#include "IEEE802_11_Radio.h"
|
||||
#include "NetVar.h"
|
||||
|
||||
using namespace zeek::packet_analysis::IEEE802_11_Radio;
|
||||
|
||||
IEEE802_11_RadioAnalyzer::IEEE802_11_RadioAnalyzer()
|
||||
: zeek::packet_analysis::Analyzer("IEEE802_11_Radio")
|
||||
{
|
||||
}
|
||||
|
||||
bool IEEE802_11_RadioAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
||||
{
|
||||
if ( 3 >= len )
|
||||
{
|
||||
packet->Weird("truncated_radiotap_header");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip over the RadioTap header
|
||||
size_t rtheader_len = (data[3] << 8) + data[2];
|
||||
|
||||
if ( rtheader_len >= len )
|
||||
{
|
||||
packet->Weird("truncated_radiotap_header");
|
||||
return false;
|
||||
}
|
||||
|
||||
return ForwardPacket(len - rtheader_len, data + rtheader_len, packet, DLT_IEEE802_11);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <packet_analysis/Analyzer.h>
|
||||
#include <packet_analysis/Component.h>
|
||||
|
||||
namespace zeek::packet_analysis::IEEE802_11_Radio {
|
||||
|
||||
class IEEE802_11_RadioAnalyzer : public Analyzer {
|
||||
public:
|
||||
IEEE802_11_RadioAnalyzer();
|
||||
~IEEE802_11_RadioAnalyzer() override = default;
|
||||
|
||||
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
|
||||
|
||||
static zeek::packet_analysis::AnalyzerPtr Instantiate()
|
||||
{
|
||||
return std::make_shared<IEEE802_11_RadioAnalyzer>();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
23
src/packet_analysis/protocol/ieee802_11_radio/Plugin.cc
Normal file
23
src/packet_analysis/protocol/ieee802_11_radio/Plugin.cc
Normal file
|
@ -0,0 +1,23 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "IEEE802_11_Radio.h"
|
||||
#include "plugin/Plugin.h"
|
||||
#include "packet_analysis/Component.h"
|
||||
|
||||
namespace zeek::plugin::Zeek_IEEE802_11_Radio {
|
||||
|
||||
class Plugin : public zeek::plugin::Plugin {
|
||||
public:
|
||||
zeek::plugin::Configuration Configure()
|
||||
{
|
||||
AddComponent(new zeek::packet_analysis::Component("IEEE802_11_Radio",
|
||||
zeek::packet_analysis::IEEE802_11_Radio::IEEE802_11_RadioAnalyzer::Instantiate));
|
||||
|
||||
zeek::plugin::Configuration config;
|
||||
config.name = "Zeek::IEEE802_11_Radio";
|
||||
config.description = "IEEE 802.11 Radiotap packet analyzer";
|
||||
return config;
|
||||
}
|
||||
|
||||
} plugin;
|
||||
}
|
8
src/packet_analysis/protocol/ip/CMakeLists.txt
Normal file
8
src/packet_analysis/protocol/ip/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
include(ZeekPlugin)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
zeek_plugin_begin(PacketAnalyzer IP)
|
||||
zeek_plugin_cc(IP.cc Plugin.cc)
|
||||
zeek_plugin_end()
|
37
src/packet_analysis/protocol/ip/IP.cc
Normal file
37
src/packet_analysis/protocol/ip/IP.cc
Normal file
|
@ -0,0 +1,37 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "IP.h"
|
||||
#include "NetVar.h"
|
||||
|
||||
using namespace zeek::packet_analysis::IP;
|
||||
|
||||
IPAnalyzer::IPAnalyzer()
|
||||
: zeek::packet_analysis::Analyzer("IP")
|
||||
{
|
||||
}
|
||||
|
||||
bool IPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
||||
{
|
||||
// Assume we're pointing at IP. Just figure out which version.
|
||||
if ( sizeof(struct ip) >= len )
|
||||
{
|
||||
packet->Weird("packet_analyzer_truncated_header");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ip = (const struct ip *)data;
|
||||
uint32_t protocol = ip->ip_v;
|
||||
|
||||
auto inner_analyzer = Lookup(protocol);
|
||||
if ( inner_analyzer == nullptr )
|
||||
{
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s failed, could not find analyzer for identifier %#x.",
|
||||
GetAnalyzerName(), protocol);
|
||||
packet->Weird("no_suitable_analyzer_found");
|
||||
return false;
|
||||
}
|
||||
|
||||
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.",
|
||||
GetAnalyzerName(), protocol);
|
||||
return inner_analyzer->AnalyzePacket(len, data, packet);
|
||||
}
|
23
src/packet_analysis/protocol/ip/IP.h
Normal file
23
src/packet_analysis/protocol/ip/IP.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <packet_analysis/Analyzer.h>
|
||||
#include <packet_analysis/Component.h>
|
||||
|
||||
namespace zeek::packet_analysis::IP {
|
||||
|
||||
class IPAnalyzer : public Analyzer {
|
||||
public:
|
||||
IPAnalyzer();
|
||||
~IPAnalyzer() override = default;
|
||||
|
||||
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
|
||||
|
||||
static zeek::packet_analysis::AnalyzerPtr Instantiate()
|
||||
{
|
||||
return std::make_shared<IPAnalyzer>();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
24
src/packet_analysis/protocol/ip/Plugin.cc
Normal file
24
src/packet_analysis/protocol/ip/Plugin.cc
Normal file
|
@ -0,0 +1,24 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "IP.h"
|
||||
#include "plugin/Plugin.h"
|
||||
#include "packet_analysis/Component.h"
|
||||
|
||||
namespace zeek::plugin::Zeek_IP {
|
||||
|
||||
class Plugin : public zeek::plugin::Plugin {
|
||||
public:
|
||||
zeek::plugin::Configuration Configure()
|
||||
{
|
||||
AddComponent(new zeek::packet_analysis::Component("IP",
|
||||
zeek::packet_analysis::IP::IPAnalyzer::Instantiate));
|
||||
|
||||
zeek::plugin::Configuration config;
|
||||
config.name = "Zeek::IP";
|
||||
config.description = "Packet analyzer for IP fallback (v4 or v6)";
|
||||
return config;
|
||||
}
|
||||
|
||||
} plugin;
|
||||
|
||||
}
|
8
src/packet_analysis/protocol/ipv4/CMakeLists.txt
Normal file
8
src/packet_analysis/protocol/ipv4/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
include(ZeekPlugin)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
zeek_plugin_begin(PacketAnalyzer IPv4)
|
||||
zeek_plugin_cc(IPv4.cc Plugin.cc)
|
||||
zeek_plugin_end()
|
20
src/packet_analysis/protocol/ipv4/IPv4.cc
Normal file
20
src/packet_analysis/protocol/ipv4/IPv4.cc
Normal file
|
@ -0,0 +1,20 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "IPv4.h"
|
||||
|
||||
using namespace zeek::packet_analysis::IPv4;
|
||||
|
||||
IPv4Analyzer::IPv4Analyzer()
|
||||
: zeek::packet_analysis::Analyzer("IPv4")
|
||||
{
|
||||
}
|
||||
|
||||
bool IPv4Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
||||
{
|
||||
packet->l3_proto = L3_IPV4;
|
||||
packet->hdr_size = static_cast<uint32_t>(data - packet->data);
|
||||
packet->session_analysis = true;
|
||||
|
||||
// Leave packet analyzer land
|
||||
return true;
|
||||
}
|
23
src/packet_analysis/protocol/ipv4/IPv4.h
Normal file
23
src/packet_analysis/protocol/ipv4/IPv4.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <packet_analysis/Analyzer.h>
|
||||
#include <packet_analysis/Component.h>
|
||||
|
||||
namespace zeek::packet_analysis::IPv4 {
|
||||
|
||||
class IPv4Analyzer : public Analyzer {
|
||||
public:
|
||||
IPv4Analyzer();
|
||||
~IPv4Analyzer() override = default;
|
||||
|
||||
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
|
||||
|
||||
static zeek::packet_analysis::AnalyzerPtr Instantiate()
|
||||
{
|
||||
return std::make_shared<IPv4Analyzer>();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
24
src/packet_analysis/protocol/ipv4/Plugin.cc
Normal file
24
src/packet_analysis/protocol/ipv4/Plugin.cc
Normal file
|
@ -0,0 +1,24 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "IPv4.h"
|
||||
#include "plugin/Plugin.h"
|
||||
#include "packet_analysis/Component.h"
|
||||
|
||||
namespace zeek::plugin::Zeek_IPv4 {
|
||||
|
||||
class Plugin : public zeek::plugin::Plugin {
|
||||
public:
|
||||
zeek::plugin::Configuration Configure()
|
||||
{
|
||||
AddComponent(new zeek::packet_analysis::Component("IPv4",
|
||||
zeek::packet_analysis::IPv4::IPv4Analyzer::Instantiate));
|
||||
|
||||
zeek::plugin::Configuration config;
|
||||
config.name = "Zeek::IPv4";
|
||||
config.description = "IPv4 packet analyzer";
|
||||
return config;
|
||||
}
|
||||
|
||||
} plugin;
|
||||
|
||||
}
|
8
src/packet_analysis/protocol/ipv6/CMakeLists.txt
Normal file
8
src/packet_analysis/protocol/ipv6/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
include(ZeekPlugin)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
zeek_plugin_begin(PacketAnalyzer IPv6)
|
||||
zeek_plugin_cc(IPv6.cc Plugin.cc)
|
||||
zeek_plugin_end()
|
20
src/packet_analysis/protocol/ipv6/IPv6.cc
Normal file
20
src/packet_analysis/protocol/ipv6/IPv6.cc
Normal file
|
@ -0,0 +1,20 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "IPv6.h"
|
||||
|
||||
using namespace zeek::packet_analysis::IPv6;
|
||||
|
||||
IPv6Analyzer::IPv6Analyzer()
|
||||
: zeek::packet_analysis::Analyzer("IPv6")
|
||||
{
|
||||
}
|
||||
|
||||
bool IPv6Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
||||
{
|
||||
packet->l3_proto = L3_IPV6;
|
||||
packet->hdr_size = static_cast<uint32_t>(data - packet->data);
|
||||
packet->session_analysis = true;
|
||||
|
||||
// Leave packet analyzer land
|
||||
return true;
|
||||
}
|
23
src/packet_analysis/protocol/ipv6/IPv6.h
Normal file
23
src/packet_analysis/protocol/ipv6/IPv6.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <packet_analysis/Analyzer.h>
|
||||
#include <packet_analysis/Component.h>
|
||||
|
||||
namespace zeek::packet_analysis::IPv6 {
|
||||
|
||||
class IPv6Analyzer : public Analyzer {
|
||||
public:
|
||||
IPv6Analyzer();
|
||||
~IPv6Analyzer() override = default;
|
||||
|
||||
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
|
||||
|
||||
static AnalyzerPtr Instantiate()
|
||||
{
|
||||
return std::make_shared<IPv6Analyzer>();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
23
src/packet_analysis/protocol/ipv6/Plugin.cc
Normal file
23
src/packet_analysis/protocol/ipv6/Plugin.cc
Normal file
|
@ -0,0 +1,23 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "plugin/Plugin.h"
|
||||
#include "IPv6.h"
|
||||
#include "packet_analysis/Component.h"
|
||||
|
||||
namespace zeek::plugin::Zeek_IPv6 {
|
||||
|
||||
class Plugin : public zeek::plugin::Plugin {
|
||||
public:
|
||||
zeek::plugin::Configuration Configure()
|
||||
{
|
||||
AddComponent(new zeek::packet_analysis::Component("IPv6",
|
||||
zeek::packet_analysis::IPv6::IPv6Analyzer::Instantiate));
|
||||
|
||||
zeek::plugin::Configuration config;
|
||||
config.name = "Zeek::IPv6";
|
||||
config.description = "IPv6 packet analyzer";
|
||||
return config;
|
||||
}
|
||||
} plugin;
|
||||
|
||||
}
|
8
src/packet_analysis/protocol/linux_sll/CMakeLists.txt
Normal file
8
src/packet_analysis/protocol/linux_sll/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
include(ZeekPlugin)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
zeek_plugin_begin(PacketAnalyzer LinuxSLL)
|
||||
zeek_plugin_cc(LinuxSLL.cc Plugin.cc)
|
||||
zeek_plugin_end()
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue