mirror of
https://github.com/zeek/zeek.git
synced 2025-10-14 12:38:20 +00:00
Merge remote-tracking branch 'origin/master' into topic/seth/scripts-for-2.1
Conflicts: scripts/base/frameworks/packet-filter/main.bro
This commit is contained in:
commit
7b19dcd0e7
353 changed files with 11398 additions and 6029 deletions
379
CHANGES
379
CHANGES
|
@ -1,7 +1,382 @@
|
|||
|
||||
2.0-306 | 2012-04-24 14:37:00 -0700
|
||||
|
||||
* Add further TLS extension values "extended_random" and
|
||||
"heartbeat". (Seth Hall)
|
||||
|
||||
* Fix problem with extracting FTP passwords and add "ftpuser" as
|
||||
another anonymous username. (Seth Hall, discovered by Patrik
|
||||
Lundin).
|
||||
|
||||
2.0-303 | 2012-04-19 10:01:06 -0700
|
||||
|
||||
* Changes related to ICMPv6 Neighbor Discovery messages. (Jon Siwek)
|
||||
|
||||
- The 'icmp_conn' record now contains an 'hlim' field since hop limit
|
||||
in the IP header is an interesting field for at least these ND
|
||||
messages.
|
||||
|
||||
- Fixed and extended 'icmp_router_advertisement' event parameters.
|
||||
|
||||
- Changed 'icmp_neighbor_advertisement' event parameters to add
|
||||
more of the known boolean flags.
|
||||
|
||||
2.0-301 | 2012-04-17 17:58:55 -0700
|
||||
|
||||
* Bro now support ICMPv6. (Matti Mantere, Jon Siwek, Robin Sommer,
|
||||
Daniel Thayer).
|
||||
|
||||
Overall, Bro now raises the following ICMP events for v4 and v6 as
|
||||
appropiate:
|
||||
|
||||
event icmp_sent(c: connection, icmp: icmp_conn);
|
||||
event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string);
|
||||
event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string);
|
||||
event icmp_error_message(c: connection, icmp: icmp_conn, code: count, context: icmp_context);
|
||||
event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context);
|
||||
event icmp_packet_too_big(c: connection, icmp: icmp_conn, code: count, context: icmp_context);
|
||||
event icmp_time_exceeded(c: connection, icmp: icmp_conn, code: count, context: icmp_context);
|
||||
event icmp_parameter_problem(c: connection, icmp: icmp_conn, code: count, context: icmp_context);
|
||||
event icmp_router_solicitation(c: connection, icmp: icmp_conn);
|
||||
event icmp_router_advertisement(c: connection, icmp: icmp_conn, hop_limit: count, managed: bool, router_lifetime: count, reachable_time: interval, retrans_timer: interval);
|
||||
event icmp_neighbor_solicitation(c: connection, icmp: icmp_conn, tgt:addr);
|
||||
event icmp_neighbor_advertisement(c: connection, icmp: icmp_conn, tgt:addr);
|
||||
event icmp_redirect(c: connection, icmp: icmp_conn, tgt: addr, dest: addr);
|
||||
|
||||
The `icmp_conn` record got a new boolean field 'v6' that indicates
|
||||
whether the ICMP message is v4 or v6.
|
||||
|
||||
This change also includes further low-level work on existing IP
|
||||
and ICMP code, including a reorganization of how ICMPv4 is
|
||||
handled.
|
||||
|
||||
2.0-281 | 2012-04-17 17:40:39 -0700
|
||||
|
||||
* Small updates for the bittorrent analyzer to support 64bit types
|
||||
in binpac. (Seth Hall)
|
||||
|
||||
* Removed the attempt at bittorrent resynchronization. (Seth Hall)
|
||||
|
||||
2.0-276 | 2012-04-17 17:35:56 -0700
|
||||
|
||||
* Add more support for <netinet/ip6.h>'s that lack some structure
|
||||
definitions. (Jon Siwek)
|
||||
|
||||
2.0-273 | 2012-04-16 18:08:56 -0700
|
||||
|
||||
* Removing QR flag from DNS log in response, which should not have
|
||||
been there in the first place. (Seth Hall)
|
||||
|
||||
* Sync up patricia.c/h with pysubnettree repo. (Daniel Thayer)
|
||||
|
||||
* Adding missing leak groups to a couple tests. Also activating leak
|
||||
checking for proxy in basic-cluster test. (Robin Sommer)
|
||||
|
||||
2.0-267 | 2012-04-09 17:47:28 -0700
|
||||
|
||||
* Add support for mobile IPv6 Mobility Header (RFC 6275). (Jon
|
||||
Siwek)
|
||||
|
||||
- Enabled through a new --enable-mobile-ipv6 configure-time
|
||||
option. If not enabled, the mobility header (routing type 2) and
|
||||
Home Address Destination option are ignored.
|
||||
|
||||
- Accessible at script-layer through 'mobile_ipv6_message' event.
|
||||
|
||||
* Refactor IP_Hdr routing header handling, add MobileIPv6 Home
|
||||
Address handling. Packets that use the Home Address Destination
|
||||
option use that option's address as the connection's originator.
|
||||
(Jon Siwek)
|
||||
|
||||
* Revert TCP checksumming to cache common data, like it did before.
|
||||
(Jon Siwek)
|
||||
|
||||
* Improve handling of IPv6 routing type 0 extension headers. (Jon
|
||||
Siwek)
|
||||
|
||||
- flow_weird event with name argument value of "routing0_hdr" is raised
|
||||
for packets containing an IPv6 routing type 0 header because this
|
||||
type of header is now deprecated according to RFC 5095.
|
||||
|
||||
- Packets with a routing type 0 header and non-zero segments left
|
||||
now use the last address in that header in order to associate
|
||||
with a connection/flow and for calculating TCP/UDP checksums.
|
||||
|
||||
- Added a set of IPv4/IPv6 TCP/UDP checksum unit tests (Jon Siwek)
|
||||
|
||||
* Fix table expiry for values assigned in bro_init() when reading
|
||||
live. (Jon Siwek)
|
||||
|
||||
2.0-257 | 2012-04-05 15:32:43 -0700
|
||||
|
||||
* Fix CMake from warning about unused ENABLE_PERFTOOLS_DEBUG
|
||||
variable. (Jon Siwek)
|
||||
|
||||
* Fix handling of IPv6 atomic fragments. (Jon Siwek)
|
||||
|
||||
* Fix that prevents Bro processes that do neither local logging nor
|
||||
request remote logs from spawning threads. (Robin Sommer)
|
||||
|
||||
* Fixing perftools-debug support. (Robin Sommer)
|
||||
|
||||
* Reverting SocketComm change tuning I/O behaviour. (Robin Sommer)
|
||||
|
||||
* Adding notice_policy.log canonification for external tests. (Robin Sommer)
|
||||
|
||||
|
||||
2.0-245 | 2012-04-04 17:25:20 -0700
|
||||
|
||||
* Internal restructuring of the logging framework: we now spawn
|
||||
threads doing the I/O. From a user's perspective not much should
|
||||
change, except that the OS may now show a bunch of Bro threads.
|
||||
(Gilbert Clark and Robin Sommer).
|
||||
|
||||
* When building Bro, we now always link in tcmalloc if it's found at
|
||||
configure time. If it's installed but not picked up,
|
||||
--with-perftools may help. (Robin Sommer)
|
||||
|
||||
* Renaming the configure option --enable-perftools to
|
||||
--enable-perftool-debug to indicate that the switch is only
|
||||
relevant for debugging the heap. It's not needed to pick up
|
||||
tcmalloc for better performance. (Robin Sommer)
|
||||
|
||||
2.0-184 | 2012-03-28 15:11:11 -0700
|
||||
|
||||
* Improve handling of IPv6 Routing Type 0 headers. (Jon Siwek)
|
||||
|
||||
- For RH0 headers with non-zero segments left, a
|
||||
"routing0_segleft" flow_weird event is raised (with a
|
||||
destination indicating the last address in the routing header),
|
||||
and an "rh0_segleft" event can also be handled if the other
|
||||
contents of the packet header are of interest. No further
|
||||
analysis is done as the complexity required to correctly
|
||||
identify destination endpoints of connections doesn't seem worth
|
||||
it as RH0 has been deprecated by RFC 5095.
|
||||
|
||||
- For RH0 headers without any segments left, a "routing0_header"
|
||||
flow_weird event is raised, but further analysis still occurs as
|
||||
normal.
|
||||
|
||||
2.0-182 | 2012-03-28 15:01:57 -0700
|
||||
|
||||
* Remove dead tcp_checksum function from net_util. (Jon Siwek)
|
||||
|
||||
* Change routing0_data_to_addrs BIF to return vector of addresses.
|
||||
The order of addresses in type 0 routing headers is
|
||||
interesting/important. (Jon Siwek)
|
||||
|
||||
|
||||
2.0-179 | 2012-03-23 17:43:31 -0700
|
||||
|
||||
* Remove the default "tcp or udp or icmp" filter. In default mode,
|
||||
Bro would load the packet filter script framework which installs a
|
||||
filter that allows all packets, but in bare mode (the -b option),
|
||||
this old filter would not follow IPv6 protocol chains and thus
|
||||
filter out packets with extension headers. (Jon Siwek)
|
||||
|
||||
* Update PacketFilter/Discarder code for IP version independence.
|
||||
(Jon Siwek)
|
||||
|
||||
* Fix some IPv6 header related bugs. (Jon Siwek)
|
||||
|
||||
* Add IPv6 fragment reassembly. (Jon Siwek)
|
||||
|
||||
* Add handling for IPv6 extension header chains. Addresses #531.
|
||||
(Jon Siwek)
|
||||
|
||||
- The script-layer 'pkt_hdr' type is extended with a new 'ip6' field
|
||||
representing the full IPv6 header chain.
|
||||
|
||||
- The 'new_packet' event is now raised for IPv6 packets. Addresses
|
||||
#523.
|
||||
|
||||
- A new event called 'ipv6_ext_header' is raised for any IPv6
|
||||
packet containing extension headers.
|
||||
|
||||
- A new event called 'esp_packet' is raised for any packets using
|
||||
ESP ('new_packet' and 'ipv6_ext_header' events provide
|
||||
connection info, but that info can't be provided here since the
|
||||
upper-layer payload is encrypted).
|
||||
|
||||
- The 'unknown_protocol' weird is now raised more reliably when
|
||||
Bro sees a transport protocol or IPv6 extension header it can't
|
||||
handle. Addresses #522.
|
||||
|
||||
* Add unit tests for IPv6 fragment reassembly, ipv6_ext_headers and
|
||||
esp_packet events. (Jon Siwek)
|
||||
|
||||
* Adapt FreeBSD's inet_ntop implementation for internal use. Now we
|
||||
get consistent text representations of IPv6 addresses across
|
||||
platforms. (Jon Siwek)
|
||||
|
||||
* Update documentation for new syntax of IPv6 literals. (Jon Siwek)
|
||||
|
||||
|
||||
2.0-150 | 2012-03-13 16:16:22 -0700
|
||||
|
||||
* Changing the regular expression to allow Site::local_nets in
|
||||
signatures. (Julien Sentier)
|
||||
|
||||
* Removing a line of dead code. Found by . Closes #786. (Julien
|
||||
Sentier)
|
||||
|
||||
2.0-146 | 2012-03-13 15:39:38 -0700
|
||||
|
||||
* Change IPv6 literal constant syntax to require encasing square
|
||||
brackets. (Jon Siwek)
|
||||
|
||||
2.0-145 | 2012-03-09 15:10:35 -0800
|
||||
|
||||
* Remove the match expression. 'match' and 'using' are no longer
|
||||
keywords. Addressed #753. (Jon Siwek)
|
||||
|
||||
2.0-143 | 2012-03-09 15:07:42 -0800
|
||||
|
||||
* Fix a BRO_PROFILER_FILE/mkstemp portability issue. Addresses #794.
|
||||
(Jon Siwek)
|
||||
|
||||
2.0-139 | 2012-03-02 09:33:04 -0800
|
||||
|
||||
* Changes to how script coverage integrates with test suites. (Jon Siwek)
|
||||
|
||||
- BRO_PROFILER_FILE now passes .X* templated filenames to mkstemp
|
||||
for generating unique coverage state files.
|
||||
|
||||
- Rearranging Makefile targets. The general rule is that if the
|
||||
all/brief target fails out due to a test failure, then the dependent
|
||||
coverage target won't run, but can still be invoked directly later.
|
||||
(e.g. make brief || make coverage)
|
||||
|
||||
* Standardized on the &default function for SSL constants. (Seth
|
||||
Hall)
|
||||
|
||||
* Adding btest group "leaks" to leak tests. (Robin Sommer)
|
||||
|
||||
* Adding btest group "comm" to communication tests for parallelizing
|
||||
execution with new btest version. (Robin Sommer)
|
||||
|
||||
* Sorting all output for diffing in the external tests. (Robin
|
||||
Sommer)
|
||||
|
||||
* Cleaned up dead code from the old SSL analyzers. Reported by
|
||||
Julien Sentier. (Seth Hall)
|
||||
|
||||
* Update/add tests for broccoli IPv6 addr/subnet support. Addresses
|
||||
#448. (Jon Siwek)
|
||||
|
||||
* Remove connection compressor. Addresses #559. (Jon Siwek)
|
||||
|
||||
* Refactor IP_Hdr class ctors. Addresses #532. (Jon Siwek)
|
||||
|
||||
|
||||
2.0-121 | 2012-02-24 16:34:17 -0800
|
||||
|
||||
* A number of smaller memory fixes and code cleanups. (Julien
|
||||
Sentier)
|
||||
|
||||
* Add to_subnet bif. Fixes #782). (Jon Siwek)
|
||||
|
||||
* Fix IPAddr::Mask/ReverseMask not allowing argument of 0. (Jon
|
||||
Siwek)
|
||||
|
||||
* Refactor IPAddr v4 initialization from string. Fixes #775. (Jon Siwek)
|
||||
|
||||
* Parse the dotted address string directly instead of canonicalizing
|
||||
and passing to inet_pton. (Jon Siwek)
|
||||
|
||||
|
||||
2.0-108 | 2012-02-24 15:21:07 -0800
|
||||
|
||||
* Refactoring a number of usages of new IPAddr class. (Jon Siwek)
|
||||
|
||||
* Fixed a bug in remask_addr bif. (Jon Siwek)
|
||||
|
||||
2.0-106 | 2012-02-24 15:02:20 -0800
|
||||
|
||||
* Raise minimum required CMake version to 2.6.3. (Jon Siwek)
|
||||
|
||||
2.0-104 | 2012-02-24 14:59:12 -0800
|
||||
|
||||
* Add test case for FTP over IPv4. (Daniel Thayer)
|
||||
|
||||
* Fix IPv6 URLs in ftp.log. (Daniel Thayer)
|
||||
|
||||
* Add a test for FTP over IPv6 (Daniel Thayer)
|
||||
|
||||
* Fix parsing of FTP EPRT command and EPSV response. (Daniel Thayer)
|
||||
|
||||
2.0-95 | 2012-02-22 05:27:34 -0800
|
||||
|
||||
* GeoIP installation documentation update. (Seth Hall)
|
||||
|
||||
* Decrease strictness of parsing IPv4 strings into addrs. Fixes #775. (Jon Siwek)
|
||||
|
||||
* Fix memory leak in DNS manager. Fixes #777. (Jon Siwek)
|
||||
|
||||
* Fix IPAddr/IPPrefix serialization bugs. (Jon Siwek)
|
||||
|
||||
* Fix compile error. (Jon Siwek)
|
||||
|
||||
2.0-86 | 2012-02-17 15:41:06 -0800
|
||||
|
||||
* Changing ARP detection to always kick in even if no analyzer is
|
||||
activated. (Robin Sommer)
|
||||
|
||||
* DNS name lookups performed by Bro now also query AAAA records.
|
||||
DNS_Mgr handles combining the results of the A and AAAA queries
|
||||
for a given hostname such that at the scripting layer, the name
|
||||
resolution can yield a set with both IPv4 and IPv6 addresses. (Jon
|
||||
Siwek)
|
||||
|
||||
* Add counts_to_addr and addr_to_counts conversion BIFs. (Jon Siwek)
|
||||
|
||||
* Change HashKey threshold for using H3 to 36 bytes. (Jon Siwek)
|
||||
|
||||
* Remove mention of --enable-brov6 in docs. (Daniel Thayer)
|
||||
|
||||
* Remove --enable-brov6 from configure usage text (Daniel Thayer)
|
||||
|
||||
* Add a test and baseline for addr_to_ptr_name BiF. (Daniel Thayer)
|
||||
|
||||
* Adding a test and baseline for ptr_name_to_addr BiF. (Seth Hall)
|
||||
|
||||
* Fix the ptr_name_to_addr BiF to work with IPv6 (Daniel Thayer)
|
||||
|
||||
* Fix a memory leak that perftools now complains about. (Jon Siwek)
|
||||
|
||||
* Remove --enable-brov6 flag, IPv6 now supported by default. (Jon Siwek)
|
||||
|
||||
Some script-layer changes of note:
|
||||
|
||||
- dns_AAAA_reply event signature changed: the string representation
|
||||
of an IPv6 addr is easily derived from the addr value, it doesn't
|
||||
need to be another parameter. This event also now generated directly
|
||||
by the DNS analyzer instead of being "faked" into a dns_A_reply event.
|
||||
|
||||
- Removed addr_to_count BIF. It used to return the host-order
|
||||
count representation of IPv4 addresses only. To make it more
|
||||
generic, we might later add a BIF to return a vector of counts
|
||||
in order to support IPv6.
|
||||
|
||||
- Changed the result of enclosing addr variables in vertical pipes
|
||||
(e.g. |my_addr|) to return the bit-width of the address type which
|
||||
is 128 for IPv6 and 32 for IPv4. It used to function the same
|
||||
way as addr_to_count mentioned above.
|
||||
|
||||
- Remove bro_has_ipv6 BIF
|
||||
|
||||
2.0-57 | 2012-02-10 00:02:35 -0800
|
||||
|
||||
* Fix typos in the documentation. (Daniel Thayer)
|
||||
|
||||
* Fix compiler warning about Brofiler ctor init list order. (Jon Siwek)
|
||||
|
||||
* Fix missing optional field access in webapp signature_match handler. (Jon Siwek)
|
||||
|
||||
2.0-41 | 2012-02-03 04:10:53 -0500
|
||||
|
||||
* Updates to the Software framework to simplify the API.
|
||||
(Bernhard Amann)
|
||||
* Updates to the Software framework to simplify the API. (Bernhard
|
||||
Amann)
|
||||
|
||||
2.0-40 | 2012-02-03 01:55:27 -0800
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
project(Bro C CXX)
|
||||
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
|
||||
cmake_minimum_required(VERSION 2.6.3 FATAL_ERROR)
|
||||
include(cmake/CommonCMakeConfig.cmake)
|
||||
|
||||
########################################################################
|
||||
|
@ -89,15 +89,29 @@ if (LIBGEOIP_FOUND)
|
|||
endif ()
|
||||
|
||||
set(USE_PERFTOOLS false)
|
||||
if (ENABLE_PERFTOOLS)
|
||||
find_package(GooglePerftools)
|
||||
if (GOOGLEPERFTOOLS_FOUND)
|
||||
set(USE_PERFTOOLS true)
|
||||
set(USE_PERFTOOLS_DEBUG false)
|
||||
|
||||
find_package(GooglePerftools)
|
||||
|
||||
if (GOOGLEPERFTOOLS_FOUND)
|
||||
include_directories(BEFORE ${GooglePerftools_INCLUDE_DIR})
|
||||
set(USE_PERFTOOLS true)
|
||||
|
||||
if (ENABLE_PERFTOOLS_DEBUG)
|
||||
# Enable heap debugging with perftools.
|
||||
set(USE_PERFTOOLS_DEBUG true)
|
||||
list(APPEND OPTLIBS ${GooglePerftools_LIBRARIES_DEBUG})
|
||||
else ()
|
||||
# Link in tcmalloc for better performance.
|
||||
list(APPEND OPTLIBS ${GooglePerftools_LIBRARIES})
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (ENABLE_PERFTOOLS_DEBUG)
|
||||
# Just a no op to prevent CMake from complaining about manually-specified
|
||||
# ENABLE_PERFTOOLS_DEBUG not being used if google perftools weren't found
|
||||
endif ()
|
||||
|
||||
set(brodeps
|
||||
${BinPAC_LIBRARY}
|
||||
${PCAP_LIBRARY}
|
||||
|
@ -183,6 +197,7 @@ message(
|
|||
"\n"
|
||||
"\nGeoIP: ${USE_GEOIP}"
|
||||
"\nGoogle perftools: ${USE_PERFTOOLS}"
|
||||
"\n debugging: ${USE_PERFTOOLS_DEBUG}"
|
||||
"\n"
|
||||
"\n================================================================\n"
|
||||
)
|
||||
|
|
2
INSTALL
2
INSTALL
|
@ -8,7 +8,7 @@ Prerequisites
|
|||
Bro relies on the following libraries and tools, which need to be installed
|
||||
before you begin:
|
||||
|
||||
* CMake 2.6 or greater http://www.cmake.org
|
||||
* CMake 2.6.3 or greater http://www.cmake.org
|
||||
|
||||
* Libpcap (headers and libraries) http://www.tcpdump.org
|
||||
|
||||
|
|
46
NEWS
46
NEWS
|
@ -5,6 +5,51 @@ Release Notes
|
|||
This document summarizes the most important changes in the current Bro
|
||||
release. For a complete list of changes, see the ``CHANGES`` file.
|
||||
|
||||
|
||||
Bro 2.1
|
||||
-------
|
||||
|
||||
- Dependencies:
|
||||
|
||||
* Bro now requires CMake >= 2.6.3.
|
||||
|
||||
* Bro now links in tcmalloc (part of Google perftools) if found at
|
||||
configure time. Doing so can significantly improve memory and
|
||||
CPU use.
|
||||
|
||||
- Bro now supports IPv6 out of the box; the configure switch
|
||||
--enable-brov6 is gone.
|
||||
|
||||
- DNS name lookups performed by Bro now also query AAAA records. The
|
||||
results of the A and AAAA queries for a given hostname are combined
|
||||
such that at the scripting layer, the name resolution can yield a
|
||||
set with both IPv4 and IPv6 addresses.
|
||||
|
||||
- The connection compressor was already deprecated in 2.0 and has now
|
||||
been removed from the code base.
|
||||
|
||||
- We removed the "match" statement, which was no longer used by any of
|
||||
the default scripts, nor was it likely to be used by anybody anytime
|
||||
soon. With that, "match" and "using" are no longer reserved keywords.
|
||||
|
||||
- The syntax for IPv6 literals changed from "2607:f8b0:4009:802::1012"
|
||||
to "[2607:f8b0:4009:802::1012]".
|
||||
|
||||
- Bro now spawn threads for doing its logging. From a user's
|
||||
perspective not much should change, except that the OS may now show
|
||||
a bunch of Bro threads.
|
||||
|
||||
- We renamed the configure option --enable-perftools to
|
||||
--enable-perftool-debug to indicate that the switch is only relevant
|
||||
for debugging the heap.
|
||||
|
||||
- Bro's ICMP analyzer now handles both IPv4 and IPv6 messages with a
|
||||
joint set of events. The `icmp_conn` record got a new boolean field
|
||||
'v6' that indicates whether the ICMP message is v4 or v6.
|
||||
|
||||
|
||||
TODO: Extend.
|
||||
|
||||
Bro 2.0
|
||||
-------
|
||||
|
||||
|
@ -61,4 +106,3 @@ final release are:
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
2.0-41
|
||||
2.0-306
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 43308aab47a3357ca1885e1b6954154a2744d821
|
||||
Subproject commit 71c37019bc371eb7863fb6aa47a7daa4540f4f1f
|
|
@ -1 +1 @@
|
|||
Subproject commit 139cc2e1e049c4e1cc7e95f20866102be1d3d599
|
||||
Subproject commit d885987e7968669e34504b0403ac89bd13928e9a
|
|
@ -1 +1 @@
|
|||
Subproject commit 930e7c78221929849086a578308e2fdc99ac3fb8
|
||||
Subproject commit 55f368b0ad283b2e7d68ef72922b5d9683e2a880
|
|
@ -1 +1 @@
|
|||
Subproject commit e908ba686dceb56065bdf569c18dd0f67f662f6b
|
||||
Subproject commit ff35c3c144885902c898bf8b47e351c7b8d55e10
|
|
@ -1 +1 @@
|
|||
Subproject commit ee87db37b520b88a55323a9767234c30b801e439
|
||||
Subproject commit 045a02749b20b3c5896497959e6fda02d060508f
|
2
cmake
2
cmake
|
@ -1 +1 @@
|
|||
Subproject commit 2cc105577044a2d214124568f3f2496ed2ccbb34
|
||||
Subproject commit 49278736c1404cb8c077272b80312c947e68bf52
|
52
config.h.in
52
config.h.in
|
@ -1,6 +1,3 @@
|
|||
/* enable IPV6 processing */
|
||||
#cmakedefine BROv6
|
||||
|
||||
/* Old libpcap versions (< 0.6.1) need defining pcap_freecode and
|
||||
pcap_compile_nopcap */
|
||||
#cmakedefine DONT_HAVE_LIBPCAP_PCAP_FREECODE
|
||||
|
@ -112,7 +109,10 @@
|
|||
#cmakedefine HAVE_GEOIP_CITY_EDITION_REV0_V6
|
||||
|
||||
/* Use Google's perftools */
|
||||
#cmakedefine USE_PERFTOOLS
|
||||
#cmakedefine USE_PERFTOOLS_DEBUG
|
||||
|
||||
/* Analyze Mobile IPv6 traffic */
|
||||
#cmakedefine ENABLE_MOBILE_IPV6
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "@VERSION@"
|
||||
|
@ -152,3 +152,47 @@
|
|||
#ifndef HAVE_DLT_PPP_SERIAL
|
||||
#define DLT_PPP_SERIAL @DLT_PPP_SERIAL@
|
||||
#endif
|
||||
|
||||
/* IPv6 Next Header values defined by RFC 3542 */
|
||||
#cmakedefine HAVE_IPPROTO_HOPOPTS
|
||||
#ifndef HAVE_IPPROTO_HOPOPTS
|
||||
#define IPPROTO_HOPOPTS 0
|
||||
#endif
|
||||
#cmakedefine HAVE_IPPROTO_IPV6
|
||||
#ifndef HAVE_IPPROTO_IPV6
|
||||
#define IPPROTO_IPV6 41
|
||||
#endif
|
||||
#cmakedefine HAVE_IPPROTO_ROUTING
|
||||
#ifndef HAVE_IPPROTO_ROUTING
|
||||
#define IPPROTO_ROUTING 43
|
||||
#endif
|
||||
#cmakedefine HAVE_IPPROTO_FRAGMENT
|
||||
#ifndef HAVE_IPPROTO_FRAGMENT
|
||||
#define IPPROTO_FRAGMENT 44
|
||||
#endif
|
||||
#cmakedefine HAVE_IPPROTO_ESP
|
||||
#ifndef HAVE_IPPROTO_ESP
|
||||
#define IPPROTO_ESP 50
|
||||
#endif
|
||||
#cmakedefine HAVE_IPPROTO_AH
|
||||
#ifndef HAVE_IPPROTO_AH
|
||||
#define IPPROTO_AH 51
|
||||
#endif
|
||||
#cmakedefine HAVE_IPPROTO_ICMPV6
|
||||
#ifndef HAVE_IPPROTO_ICMPV6
|
||||
#define IPPROTO_ICMPV6 58
|
||||
#endif
|
||||
#cmakedefine HAVE_IPPROTO_NONE
|
||||
#ifndef HAVE_IPPROTO_NONE
|
||||
#define IPPROTO_NONE 59
|
||||
#endif
|
||||
#cmakedefine HAVE_IPPROTO_DSTOPTS
|
||||
#ifndef HAVE_IPPROTO_DSTOPTS
|
||||
#define IPPROTO_DSTOPTS 60
|
||||
#endif
|
||||
|
||||
/* IPv6 options structure defined by RFC 3542 */
|
||||
#cmakedefine HAVE_IP6_OPT
|
||||
|
||||
/* Common IPv6 extension structure */
|
||||
#cmakedefine HAVE_IP6_EXT
|
||||
|
|
44
configure
vendored
44
configure
vendored
|
@ -24,11 +24,12 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
|
|||
--prefix=PREFIX installation directory [/usr/local/bro]
|
||||
--scriptdir=PATH root installation directory for Bro scripts
|
||||
[PREFIX/share/bro]
|
||||
--conf-files-dir=PATH config files installation directory [PREFIX/etc]
|
||||
|
||||
Optional Features:
|
||||
--enable-debug compile in debugging mode
|
||||
--enable-brov6 enable IPv6 processing
|
||||
--enable-perftools use Google's perftools
|
||||
--enable-mobile-ipv6 analyze mobile IPv6 features defined by RFC 6275
|
||||
--enable-perftools-debug use Google's perftools for debugging
|
||||
--disable-broccoli don't build or install the Broccoli library
|
||||
--disable-broctl don't install Broctl
|
||||
--disable-auxtools don't build or install auxilliary tools
|
||||
|
@ -86,20 +87,22 @@ append_cache_entry () {
|
|||
|
||||
# set defaults
|
||||
builddir=build
|
||||
prefix=/usr/local/bro
|
||||
CMakeCacheEntries=""
|
||||
append_cache_entry CMAKE_INSTALL_PREFIX PATH /usr/local/bro
|
||||
append_cache_entry BRO_ROOT_DIR PATH /usr/local/bro
|
||||
append_cache_entry PY_MOD_INSTALL_DIR PATH /usr/local/bro/lib/broctl
|
||||
append_cache_entry BRO_SCRIPT_INSTALL_PATH STRING /usr/local/bro/share/bro
|
||||
append_cache_entry CMAKE_INSTALL_PREFIX PATH $prefix
|
||||
append_cache_entry BRO_ROOT_DIR PATH $prefix
|
||||
append_cache_entry PY_MOD_INSTALL_DIR PATH $prefix/lib/broctl
|
||||
append_cache_entry BRO_SCRIPT_INSTALL_PATH STRING $prefix/share/bro
|
||||
append_cache_entry BRO_ETC_INSTALL_DIR PATH $prefix/etc
|
||||
append_cache_entry ENABLE_DEBUG BOOL false
|
||||
append_cache_entry BROv6 BOOL false
|
||||
append_cache_entry ENABLE_PERFTOOLS BOOL false
|
||||
append_cache_entry ENABLE_PERFTOOLS_DEBUG BOOL false
|
||||
append_cache_entry BinPAC_SKIP_INSTALL BOOL true
|
||||
append_cache_entry BUILD_SHARED_LIBS BOOL true
|
||||
append_cache_entry INSTALL_AUX_TOOLS BOOL true
|
||||
append_cache_entry INSTALL_BROCCOLI BOOL true
|
||||
append_cache_entry INSTALL_BROCTL BOOL true
|
||||
append_cache_entry CPACK_SOURCE_IGNORE_FILES STRING
|
||||
append_cache_entry ENABLE_MOBILE_IPV6 BOOL false
|
||||
|
||||
# parse arguments
|
||||
while [ $# -ne 0 ]; do
|
||||
|
@ -120,25 +123,27 @@ while [ $# -ne 0 ]; do
|
|||
CMakeGenerator="$optarg"
|
||||
;;
|
||||
--prefix=*)
|
||||
prefix=$optarg
|
||||
append_cache_entry CMAKE_INSTALL_PREFIX PATH $optarg
|
||||
append_cache_entry BRO_ROOT_DIR PATH $optarg
|
||||
append_cache_entry PY_MOD_INSTALL_DIR PATH $optarg/lib/broctl
|
||||
if [ "$user_set_scriptdir" != "true" ]; then
|
||||
append_cache_entry BRO_SCRIPT_INSTALL_PATH STRING $optarg/share/bro
|
||||
fi
|
||||
;;
|
||||
--scriptdir=*)
|
||||
append_cache_entry BRO_SCRIPT_INSTALL_PATH STRING $optarg
|
||||
user_set_scriptdir="true"
|
||||
;;
|
||||
--conf-files-dir=*)
|
||||
append_cache_entry BRO_ETC_INSTALL_DIR PATH $optarg
|
||||
user_set_conffilesdir="true"
|
||||
;;
|
||||
--enable-debug)
|
||||
append_cache_entry ENABLE_DEBUG BOOL true
|
||||
;;
|
||||
--enable-brov6)
|
||||
append_cache_entry BROv6 BOOL true
|
||||
--enable-mobile-ipv6)
|
||||
append_cache_entry ENABLE_MOBILE_IPV6 BOOL true
|
||||
;;
|
||||
--enable-perftools)
|
||||
append_cache_entry ENABLE_PERFTOOLS BOOL true
|
||||
--enable-perftools-debug)
|
||||
append_cache_entry ENABLE_PERFTOOLS_DEBUG BOOL true
|
||||
;;
|
||||
--disable-broccoli)
|
||||
append_cache_entry INSTALL_BROCCOLI BOOL false
|
||||
|
@ -183,7 +188,6 @@ while [ $# -ne 0 ]; do
|
|||
append_cache_entry LibGeoIP_ROOT_DIR PATH $optarg
|
||||
;;
|
||||
--with-perftools=*)
|
||||
append_cache_entry ENABLE_PERFTOOLS BOOL true
|
||||
append_cache_entry GooglePerftools_ROOT_DIR PATH $optarg
|
||||
;;
|
||||
--with-python=*)
|
||||
|
@ -232,6 +236,14 @@ while [ $# -ne 0 ]; do
|
|||
shift
|
||||
done
|
||||
|
||||
if [ "$user_set_scriptdir" != "true" ]; then
|
||||
append_cache_entry BRO_SCRIPT_INSTALL_PATH STRING $prefix/share/bro
|
||||
fi
|
||||
|
||||
if [ "$user_set_conffilesdir" != "true" ]; then
|
||||
append_cache_entry BRO_ETC_INSTALL_DIR PATH $prefix/etc
|
||||
fi
|
||||
|
||||
if [ -d $builddir ]; then
|
||||
# If build directory exists, check if it has a CMake cache
|
||||
if [ -f $builddir/CMakeCache.txt ]; then
|
||||
|
|
|
@ -103,7 +103,13 @@ Optional Dependencies
|
|||
Bro can use libGeoIP for geo-locating IP addresses, and sendmail for
|
||||
sending emails.
|
||||
|
||||
* RPM/RedHat-based Linux:
|
||||
* RedHat Enterprise Linux:
|
||||
|
||||
.. console::
|
||||
|
||||
sudo yum install geoip-devel sendmail
|
||||
|
||||
* CentOS Linux:
|
||||
|
||||
.. console::
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ The Bro scripting language supports the following built-in types.
|
|||
is a string of digits preceded by a ``+`` or ``-`` sign, e.g.
|
||||
``-42`` or ``+5``. When using type inferencing use care so that the
|
||||
intended type is inferred, e.g. ``local size_difference = 0`` will
|
||||
infer the :bro:type:`count` while ``local size_difference = +0``
|
||||
infer :bro:type:`count`, while ``local size_difference = +0``
|
||||
will infer :bro:type:`int`.
|
||||
|
||||
.. bro:type:: count
|
||||
|
@ -32,7 +32,7 @@ The Bro scripting language supports the following built-in types.
|
|||
|
||||
.. bro:type:: counter
|
||||
|
||||
An alias to :bro:type:`count`
|
||||
An alias to :bro:type:`count`.
|
||||
|
||||
.. TODO: is there anything special about this type?
|
||||
|
||||
|
@ -70,7 +70,7 @@ The Bro scripting language supports the following built-in types.
|
|||
|
||||
A type used to hold character-string values which represent text.
|
||||
String constants are created by enclosing text in double quotes (")
|
||||
and the backslash character (\) introduces escape sequences.
|
||||
and the backslash character (\\) introduces escape sequences.
|
||||
|
||||
Note that Bro represents strings internally as a count and vector of
|
||||
bytes rather than a NUL-terminated byte string (although string
|
||||
|
@ -135,7 +135,7 @@ The Bro scripting language supports the following built-in types.
|
|||
|
||||
type color: enum { Red, White, Blue, };
|
||||
|
||||
The last comma is after ``Blue`` is optional.
|
||||
The last comma after ``Blue`` is optional.
|
||||
|
||||
.. bro:type:: timer
|
||||
|
||||
|
@ -150,21 +150,23 @@ The Bro scripting language supports the following built-in types.
|
|||
followed by one of ``/tcp``, ``/udp``, ``/icmp``, or ``/unknown``.
|
||||
|
||||
Ports can be compared for equality and also for ordering. When
|
||||
comparing order across transport-level protocols, ``/unknown`` <
|
||||
``/tcp`` < ``/udp`` < ``icmp``, for example ``65535/tcp`` is smaller
|
||||
comparing order across transport-level protocols, ``unknown`` <
|
||||
``tcp`` < ``udp`` < ``icmp``, for example ``65535/tcp`` is smaller
|
||||
than ``0/udp``.
|
||||
|
||||
.. bro:type:: addr
|
||||
|
||||
A type representing an IP address. Currently, Bro defaults to only
|
||||
supporting IPv4 addresses unless configured/built with
|
||||
``--enable-brov6``, in which case, IPv6 addresses are supported.
|
||||
A type representing an IP address.
|
||||
|
||||
IPv4 address constants are written in "dotted quad" format,
|
||||
``A1.A2.A3.A4``, where Ai all lie between 0 and 255.
|
||||
|
||||
IPv6 address constants are written as colon-separated hexadecimal form
|
||||
as described by :rfc:`2373`.
|
||||
as described by :rfc:`2373`, but additionally encased in square brackets.
|
||||
The mixed notation with embedded IPv4 addresses as dotted-quads in the
|
||||
lower 32 bits is also allowed.
|
||||
Some examples: ``[2001:db8::1]``, ``[::ffff:192.168.1.100]``, or
|
||||
``[aaaa:bbbb:cccc:dddd:eeee:ffff:1111:2222]``.
|
||||
|
||||
Hostname constants can also be used, but since a hostname can
|
||||
correspond to multiple IP addresses, the type of such variable is a
|
||||
|
@ -198,7 +200,7 @@ The Bro scripting language supports the following built-in types.
|
|||
A type representing a block of IP addresses in CIDR notation. A
|
||||
``subnet`` constant is written as an :bro:type:`addr` followed by a
|
||||
slash (/) and then the network prefix size specified as a decimal
|
||||
number. For example, ``192.168.0.0/16``.
|
||||
number. For example, ``192.168.0.0/16`` or ``[fe80::]/64``.
|
||||
|
||||
.. bro:type:: any
|
||||
|
||||
|
@ -230,7 +232,7 @@ The Bro scripting language supports the following built-in types.
|
|||
|
||||
global a: table[count] of table[addr, port] of string;
|
||||
|
||||
which declared a table indexed by :bro:type:`count` and yielding
|
||||
which declares a table indexed by :bro:type:`count` and yielding
|
||||
another :bro:type:`table` which is indexed by an :bro:type:`addr`
|
||||
and :bro:type:`port` to yield a :bro:type:`string`.
|
||||
|
||||
|
@ -392,7 +394,7 @@ The Bro scripting language supports the following built-in types.
|
|||
:bro:attr:`&optional` or have a :bro:attr:`&default` attribute must
|
||||
be specified.
|
||||
|
||||
To test for existence of field that is :bro:attr:`&optional`, use the
|
||||
To test for existence of a field that is :bro:attr:`&optional`, use the
|
||||
``?$`` operator:
|
||||
|
||||
.. code:: bro
|
||||
|
@ -412,7 +414,7 @@ The Bro scripting language supports the following built-in types.
|
|||
print f, "hello, world";
|
||||
close(f);
|
||||
|
||||
Writing to files like this for logging usually isn't recommend, for better
|
||||
Writing to files like this for logging usually isn't recommended, for better
|
||||
logging support see :doc:`/logging`.
|
||||
|
||||
.. bro:type:: func
|
||||
|
@ -512,22 +514,22 @@ scripting language supports the following built-in attributes.
|
|||
|
||||
.. bro:attr:: &optional
|
||||
|
||||
Allows record field to be missing. For example the type ``record {
|
||||
Allows a record field to be missing. For example the type ``record {
|
||||
a: int, b: port &optional }`` could be instantiated both as
|
||||
singleton ``[$a=127.0.0.1]`` or pair ``[$a=127.0.0.1, $b=80/tcp]``.
|
||||
|
||||
.. bro:attr:: &default
|
||||
|
||||
Uses a default value for a record field or container elements. For
|
||||
example, ``table[int] of string &default="foo" }`` would create
|
||||
table that returns The :bro:type:`string` ``"foo"`` for any
|
||||
example, ``table[int] of string &default="foo" }`` would create a
|
||||
table that returns the :bro:type:`string` ``"foo"`` for any
|
||||
non-existing index.
|
||||
|
||||
.. bro:attr:: &redef
|
||||
|
||||
Allows for redefinition of initial object values. This is typically
|
||||
used with constants, for example, ``const clever = T &redef;`` would
|
||||
allow the constant to be redifined at some later point during script
|
||||
allow the constant to be redefined at some later point during script
|
||||
execution.
|
||||
|
||||
.. bro:attr:: &rotate_interval
|
||||
|
@ -536,7 +538,7 @@ scripting language supports the following built-in attributes.
|
|||
|
||||
.. bro:attr:: &rotate_size
|
||||
|
||||
Rotates af file after it has reached a given size in bytes.
|
||||
Rotates a file after it has reached a given size in bytes.
|
||||
|
||||
.. bro:attr:: &add_func
|
||||
|
||||
|
@ -548,7 +550,12 @@ scripting language supports the following built-in attributes.
|
|||
|
||||
.. bro:attr:: &expire_func
|
||||
|
||||
Called right before a container element expires.
|
||||
Called right before a container element expires. The function's
|
||||
first parameter is of the same type of the container and the second
|
||||
parameter the same type of the container's index. The return
|
||||
value is a :bro:type:`interval` indicating the amount of additional
|
||||
time to wait before expiring the container element at the given
|
||||
index (which will trigger another execution of this function).
|
||||
|
||||
.. bro:attr:: &read_expire
|
||||
|
||||
|
|
|
@ -46,6 +46,13 @@ type index_vec: vector of count;
|
|||
## then remove this alias.
|
||||
type string_vec: vector of string;
|
||||
|
||||
## A vector of addresses.
|
||||
##
|
||||
## .. todo:: We need this type definition only for declaring builtin functions via
|
||||
## ``bifcl``. We should extend ``bifcl`` to understand composite types directly and
|
||||
## then remove this alias.
|
||||
type addr_vec: vector of addr;
|
||||
|
||||
## A table of strings indexed by strings.
|
||||
##
|
||||
## .. todo:: We need this type definition only for declaring builtin functions via
|
||||
|
@ -85,6 +92,8 @@ type icmp_conn: record {
|
|||
itype: count; ##< The ICMP type of the packet that triggered the instantiation of the record.
|
||||
icode: count; ##< The ICMP code of the packet that triggered the instantiation of the record.
|
||||
len: count; ##< The length of the ICMP payload of the packet that triggered the instantiation of the record.
|
||||
hlim: count; ##< The encapsulating IP header's Hop Limit value.
|
||||
v6: bool; ##< True if it's an ICMPv6 packet.
|
||||
};
|
||||
|
||||
## Packet context part of an ICMP message. The fields of this record reflect the
|
||||
|
@ -93,11 +102,13 @@ type icmp_conn: record {
|
|||
## .. bro:see:: icmp_time_exceeded icmp_unreachable
|
||||
type icmp_context: record {
|
||||
id: conn_id; ##< The packet's 4-tuple.
|
||||
len: count; ##< The lenght of the packet's IP header.
|
||||
len: count; ##< The length of the IP packet (headers + payload).
|
||||
proto: count; ##< The packet's transport-layer protocol.
|
||||
frag_offset: count; ##< The packet's fragementation offset.
|
||||
## True if the packet's IP header is fully included in the context. If that is not
|
||||
## the case, the other fields will all be set to null values.
|
||||
## True if the packet's IP header is not fully included in the context
|
||||
## or if there is not enough of the transport header to determine source
|
||||
## and destination ports. If that is the cast, the appropriate fields
|
||||
## of this record will be set to null values.
|
||||
bad_hdr_len: bool;
|
||||
bad_checksum: bool; ##< True if the packet's IP checksum is not correct.
|
||||
MF: bool; ##< True if the packets *more fragements* flag is set.
|
||||
|
@ -601,10 +612,10 @@ function add_signature_file(sold: string, snew: string): string
|
|||
}
|
||||
|
||||
## Signature files to read. Use ``redef signature_files += "foo.sig"`` to
|
||||
## extend. Signature files will be searched relative to ``BRO_PATH``.
|
||||
## extend. Signature files will be searched relative to ``BROPATH``.
|
||||
global signature_files = "" &add_func = add_signature_file;
|
||||
|
||||
## ``p0f`` fingerprint file to use. Will be searched relative to ``BRO_PATH``.
|
||||
## ``p0f`` fingerprint file to use. Will be searched relative to ``BROPATH``.
|
||||
const passive_fingerprint_file = "base/misc/p0f.fp" &redef;
|
||||
|
||||
# TCP values for :bro:see:`endpoint` *state* field.
|
||||
|
@ -926,12 +937,319 @@ const IPPROTO_IGMP = 2; ##< Group management protocol.
|
|||
const IPPROTO_IPIP = 4; ##< IP encapsulation in IP.
|
||||
const IPPROTO_TCP = 6; ##< TCP.
|
||||
const IPPROTO_UDP = 17; ##< User datagram protocol.
|
||||
const IPPROTO_IPV6 = 41; ##< IPv6 header.
|
||||
const IPPROTO_ICMPV6 = 58; ##< ICMP for IPv6.
|
||||
const IPPROTO_RAW = 255; ##< Raw IP packet.
|
||||
|
||||
## Values extracted from an IP header.
|
||||
# Definitions for IPv6 extension headers.
|
||||
const IPPROTO_HOPOPTS = 0; ##< IPv6 hop-by-hop-options header.
|
||||
const IPPROTO_ROUTING = 43; ##< IPv6 routing header.
|
||||
const IPPROTO_FRAGMENT = 44; ##< IPv6 fragment header.
|
||||
const IPPROTO_ESP = 50; ##< IPv6 encapsulating security payload header.
|
||||
const IPPROTO_AH = 51; ##< IPv6 authentication header.
|
||||
const IPPROTO_NONE = 59; ##< IPv6 no next header.
|
||||
const IPPROTO_DSTOPTS = 60; ##< IPv6 destination options header.
|
||||
const IPPROTO_MOBILITY = 135; ##< IPv6 mobility header.
|
||||
|
||||
## Values extracted from an IPv6 extension header's (e.g. hop-by-hop or
|
||||
## destination option headers) option field.
|
||||
##
|
||||
## .. bro:see:: pkt_hdr discarder_check_ip
|
||||
type ip_hdr: record {
|
||||
## .. bro:see:: ip6_hdr ip6_hdr_chain ip6_hopopts ip6_dstopts
|
||||
type ip6_option: record {
|
||||
otype: count; ##< Option type.
|
||||
len: count; ##< Option data length.
|
||||
data: string; ##< Option data.
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Hop-by-Hop options extension header.
|
||||
##
|
||||
## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain ip6_option
|
||||
type ip6_hopopts: record {
|
||||
## Protocol number of the next header (RFC 1700 et seq., IANA assigned
|
||||
## number), e.g. :bro:id:`IPPROTO_ICMP`.
|
||||
nxt: count;
|
||||
## Length of header in 8-octet units, excluding first unit.
|
||||
len: count;
|
||||
## The TLV encoded options;
|
||||
options: vector of ip6_option;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Destination options extension header.
|
||||
##
|
||||
## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain ip6_option
|
||||
type ip6_dstopts: record {
|
||||
## Protocol number of the next header (RFC 1700 et seq., IANA assigned
|
||||
## number), e.g. :bro:id:`IPPROTO_ICMP`.
|
||||
nxt: count;
|
||||
## Length of header in 8-octet units, excluding first unit.
|
||||
len: count;
|
||||
## The TLV encoded options;
|
||||
options: vector of ip6_option;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Routing extension header.
|
||||
##
|
||||
## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain
|
||||
type ip6_routing: record {
|
||||
## Protocol number of the next header (RFC 1700 et seq., IANA assigned
|
||||
## number), e.g. :bro:id:`IPPROTO_ICMP`.
|
||||
nxt: count;
|
||||
## Length of header in 8-octet units, excluding first unit.
|
||||
len: count;
|
||||
## Routing type.
|
||||
rtype: count;
|
||||
## Segments left.
|
||||
segleft: count;
|
||||
## Type-specific data.
|
||||
data: string;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Fragment extension header.
|
||||
##
|
||||
## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain
|
||||
type ip6_fragment: record {
|
||||
## Protocol number of the next header (RFC 1700 et seq., IANA assigned
|
||||
## number), e.g. :bro:id:`IPPROTO_ICMP`.
|
||||
nxt: count;
|
||||
## 8-bit reserved field.
|
||||
rsv1: count;
|
||||
## Fragmentation offset.
|
||||
offset: count;
|
||||
## 2-bit reserved field.
|
||||
rsv2: count;
|
||||
## More fragments.
|
||||
more: bool;
|
||||
## Fragment identification.
|
||||
id: count;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Authentication extension header.
|
||||
##
|
||||
## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain
|
||||
type ip6_ah: record {
|
||||
## Protocol number of the next header (RFC 1700 et seq., IANA assigned
|
||||
## number), e.g. :bro:id:`IPPROTO_ICMP`.
|
||||
nxt: count;
|
||||
## Length of header in 4-octet units, excluding first two units.
|
||||
len: count;
|
||||
## Reserved field.
|
||||
rsv: count;
|
||||
## Security Parameter Index.
|
||||
spi: count;
|
||||
## Sequence number.
|
||||
seq: count;
|
||||
## Authentication data.
|
||||
data: string;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 ESP extension header.
|
||||
##
|
||||
## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain
|
||||
type ip6_esp: record {
|
||||
## Security Parameters Index.
|
||||
spi: count;
|
||||
## Sequence number.
|
||||
seq: count;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Mobility Binding Refresh Request message.
|
||||
##
|
||||
## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg
|
||||
type ip6_mobility_brr: record {
|
||||
## Reserved.
|
||||
rsv: count;
|
||||
## Mobility Options.
|
||||
options: vector of ip6_option;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Mobility Home Test Init message.
|
||||
##
|
||||
## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg
|
||||
type ip6_mobility_hoti: record {
|
||||
## Reserved.
|
||||
rsv: count;
|
||||
## Home Init Cookie.
|
||||
cookie: count;
|
||||
## Mobility Options.
|
||||
options: vector of ip6_option;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Mobility Care-of Test Init message.
|
||||
##
|
||||
## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg
|
||||
type ip6_mobility_coti: record {
|
||||
## Reserved.
|
||||
rsv: count;
|
||||
## Care-of Init Cookie.
|
||||
cookie: count;
|
||||
## Mobility Options.
|
||||
options: vector of ip6_option;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Mobility Home Test message.
|
||||
##
|
||||
## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg
|
||||
type ip6_mobility_hot: record {
|
||||
## Home Nonce Index.
|
||||
nonce_idx: count;
|
||||
## Home Init Cookie.
|
||||
cookie: count;
|
||||
## Home Keygen Token.
|
||||
token: count;
|
||||
## Mobility Options.
|
||||
options: vector of ip6_option;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Mobility Care-of Test message.
|
||||
##
|
||||
## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg
|
||||
type ip6_mobility_cot: record {
|
||||
## Care-of Nonce Index.
|
||||
nonce_idx: count;
|
||||
## Care-of Init Cookie.
|
||||
cookie: count;
|
||||
## Care-of Keygen Token.
|
||||
token: count;
|
||||
## Mobility Options.
|
||||
options: vector of ip6_option;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Mobility Binding Update message.
|
||||
##
|
||||
## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg
|
||||
type ip6_mobility_bu: record {
|
||||
## Sequence number.
|
||||
seq: count;
|
||||
## Acknowledge bit.
|
||||
a: bool;
|
||||
## Home Registration bit.
|
||||
h: bool;
|
||||
## Link-Local Address Compatibility bit.
|
||||
l: bool;
|
||||
## Key Management Mobility Capability bit.
|
||||
k: bool;
|
||||
## Lifetime.
|
||||
life: count;
|
||||
## Mobility Options.
|
||||
options: vector of ip6_option;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Mobility Binding Acknowledgement message.
|
||||
##
|
||||
## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg
|
||||
type ip6_mobility_back: record {
|
||||
## Status.
|
||||
status: count;
|
||||
## Key Management Mobility Capability.
|
||||
k: bool;
|
||||
## Sequence number.
|
||||
seq: count;
|
||||
## Lifetime.
|
||||
life: count;
|
||||
## Mobility Options.
|
||||
options: vector of ip6_option;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Mobility Binding Error message.
|
||||
##
|
||||
## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg
|
||||
type ip6_mobility_be: record {
|
||||
## Status.
|
||||
status: count;
|
||||
## Home Address.
|
||||
hoa: addr;
|
||||
## Mobility Options.
|
||||
options: vector of ip6_option;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Mobility header's message data.
|
||||
##
|
||||
## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain
|
||||
type ip6_mobility_msg: record {
|
||||
## The type of message from the header's MH Type field.
|
||||
id: count;
|
||||
## Binding Refresh Request.
|
||||
brr: ip6_mobility_brr &optional;
|
||||
## Home Test Init.
|
||||
hoti: ip6_mobility_hoti &optional;
|
||||
## Care-of Test Init.
|
||||
coti: ip6_mobility_coti &optional;
|
||||
## Home Test.
|
||||
hot: ip6_mobility_hot &optional;
|
||||
## Care-of Test.
|
||||
cot: ip6_mobility_cot &optional;
|
||||
## Binding Update.
|
||||
bu: ip6_mobility_bu &optional;
|
||||
## Binding Acknowledgement.
|
||||
back: ip6_mobility_back &optional;
|
||||
## Binding Error.
|
||||
be: ip6_mobility_be &optional;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 Mobility header.
|
||||
##
|
||||
## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain
|
||||
type ip6_mobility_hdr: record {
|
||||
## Protocol number of the next header (RFC 1700 et seq., IANA assigned
|
||||
## number), e.g. :bro:id:`IPPROTO_ICMP`.
|
||||
nxt: count;
|
||||
## Length of header in 8-octet units, excluding first unit.
|
||||
len: count;
|
||||
## Mobility header type used to identify header's the message.
|
||||
mh_type: count;
|
||||
## Reserved field.
|
||||
rsv: count;
|
||||
## Mobility header checksum.
|
||||
chksum: count;
|
||||
## Mobility header message
|
||||
msg: ip6_mobility_msg;
|
||||
};
|
||||
|
||||
## A general container for a more specific IPv6 extension header.
|
||||
##
|
||||
## .. bro:see:: pkt_hdr ip4_hdr ip6_hopopts ip6_dstopts ip6_routing ip6_fragment
|
||||
## ip6_ah ip6_esp
|
||||
type ip6_ext_hdr: record {
|
||||
## The RFC 1700 et seq. IANA assigned number identifying the type of
|
||||
## the extension header.
|
||||
id: count;
|
||||
## Hop-by-hop option extension header.
|
||||
hopopts: ip6_hopopts &optional;
|
||||
## Destination option extension header.
|
||||
dstopts: ip6_dstopts &optional;
|
||||
## Routing extension header.
|
||||
routing: ip6_routing &optional;
|
||||
## Fragment header.
|
||||
fragment: ip6_fragment &optional;
|
||||
## Authentication extension header.
|
||||
ah: ip6_ah &optional;
|
||||
## Encapsulating security payload header.
|
||||
esp: ip6_esp &optional;
|
||||
## Mobility header.
|
||||
mobility: ip6_mobility_hdr &optional;
|
||||
};
|
||||
|
||||
## Values extracted from an IPv6 header.
|
||||
##
|
||||
## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr_chain ip6_hopopts ip6_dstopts
|
||||
## ip6_routing ip6_fragment ip6_ah ip6_esp
|
||||
type ip6_hdr: record {
|
||||
class: count; ##< Traffic class.
|
||||
flow: count; ##< Flow label.
|
||||
len: count; ##< Payload length.
|
||||
nxt: count; ##< Protocol number of the next header
|
||||
##< (RFC 1700 et seq., IANA assigned number)
|
||||
##< e.g. :bro:id:`IPPROTO_ICMP`.
|
||||
hlim: count; ##< Hop limit.
|
||||
src: addr; ##< Source address.
|
||||
dst: addr; ##< Destination address.
|
||||
exts: vector of ip6_ext_hdr; ##< Extension header chain.
|
||||
};
|
||||
|
||||
## Values extracted from an IPv4 header.
|
||||
##
|
||||
## .. bro:see:: pkt_hdr ip6_hdr discarder_check_ip
|
||||
type ip4_hdr: record {
|
||||
hl: count; ##< Header length in bytes.
|
||||
tos: count; ##< Type of service.
|
||||
len: count; ##< Total length.
|
||||
|
@ -987,7 +1305,8 @@ type icmp_hdr: record {
|
|||
##
|
||||
## .. bro:see:: new_packet
|
||||
type pkt_hdr: record {
|
||||
ip: ip_hdr; ##< The IP header.
|
||||
ip: ip4_hdr &optional; ##< The IPv4 header if an IPv4 packet.
|
||||
ip6: ip6_hdr &optional; ##< The IPv6 header if an IPv6 packet.
|
||||
tcp: tcp_hdr &optional; ##< The TCP header if a TCP packet.
|
||||
udp: udp_hdr &optional; ##< The UDP header if a UDP packet.
|
||||
icmp: icmp_hdr &optional; ##< The ICMP header if an ICMP packet.
|
||||
|
@ -1010,7 +1329,7 @@ global discarder_maxlen = 128 &redef;
|
|||
## analysis. If the function signals to discard a packet, no further processing
|
||||
## will be performed on it.
|
||||
##
|
||||
## i: The IP header of the considered packet.
|
||||
## p: The IP header of the considered packet.
|
||||
##
|
||||
## Returns: True if the packet should not be analyzed any further.
|
||||
##
|
||||
|
@ -1019,15 +1338,15 @@ global discarder_maxlen = 128 &redef;
|
|||
##
|
||||
## .. note:: This is very low-level functionality and potentially expensive.
|
||||
## Avoid using it.
|
||||
global discarder_check_ip: function(i: ip_hdr): bool;
|
||||
global discarder_check_ip: function(p: pkt_hdr): bool;
|
||||
|
||||
## Function for skipping packets based on their TCP header. If defined, this
|
||||
## function will be called for all TCP packets before Bro performs any further
|
||||
## analysis. If the function signals to discard a packet, no further processing
|
||||
## will be performed on it.
|
||||
##
|
||||
## i: The IP header of the considered packet.
|
||||
## t: The TCP header.
|
||||
## p: The IP and TCP headers of the considered packet.
|
||||
##
|
||||
## d: Up to :bro:see:`discarder_maxlen` bytes of the TCP payload.
|
||||
##
|
||||
## Returns: True if the packet should not be analyzed any further.
|
||||
|
@ -1037,15 +1356,15 @@ global discarder_check_ip: function(i: ip_hdr): bool;
|
|||
##
|
||||
## .. note:: This is very low-level functionality and potentially expensive.
|
||||
## Avoid using it.
|
||||
global discarder_check_tcp: function(i: ip_hdr, t: tcp_hdr, d: string): bool;
|
||||
global discarder_check_tcp: function(p: pkt_hdr, d: string): bool;
|
||||
|
||||
## Function for skipping packets based on their UDP header. If defined, this
|
||||
## function will be called for all UDP packets before Bro performs any further
|
||||
## analysis. If the function signals to discard a packet, no further processing
|
||||
## will be performed on it.
|
||||
##
|
||||
## i: The IP header of the considered packet.
|
||||
## t: The UDP header.
|
||||
## p: The IP and UDP headers of the considered packet.
|
||||
##
|
||||
## d: Up to :bro:see:`discarder_maxlen` bytes of the UDP payload.
|
||||
##
|
||||
## Returns: True if the packet should not be analyzed any further.
|
||||
|
@ -1055,15 +1374,14 @@ global discarder_check_tcp: function(i: ip_hdr, t: tcp_hdr, d: string): bool;
|
|||
##
|
||||
## .. note:: This is very low-level functionality and potentially expensive.
|
||||
## Avoid using it.
|
||||
global discarder_check_udp: function(i: ip_hdr, u: udp_hdr, d: string): bool;
|
||||
global discarder_check_udp: function(p: pkt_hdr, d: string): bool;
|
||||
|
||||
## Function for skipping packets based on their ICMP header. If defined, this
|
||||
## function will be called for all ICMP packets before Bro performs any further
|
||||
## analysis. If the function signals to discard a packet, no further processing
|
||||
## will be performed on it.
|
||||
##
|
||||
## i: The IP header of the considered packet.
|
||||
## ih: The ICMP header.
|
||||
## p: The IP and ICMP headers of the considered packet.
|
||||
##
|
||||
## Returns: True if the packet should not be analyzed any further.
|
||||
##
|
||||
|
@ -1072,7 +1390,7 @@ global discarder_check_udp: function(i: ip_hdr, u: udp_hdr, d: string): bool;
|
|||
##
|
||||
## .. note:: This is very low-level functionality and potentially expensive.
|
||||
## Avoid using it.
|
||||
global discarder_check_icmp: function(i: ip_hdr, ih: icmp_hdr): bool;
|
||||
global discarder_check_icmp: function(p: pkt_hdr): bool;
|
||||
|
||||
## Bro's watchdog interval.
|
||||
const watchdog_interval = 10 sec &redef;
|
||||
|
@ -1706,13 +2024,6 @@ global dns_skip_all_addl = T &redef;
|
|||
## traffic and do not process it. Set to 0 to turn off this functionality.
|
||||
global dns_max_queries = 5;
|
||||
|
||||
## The maxiumum size in bytes for an SSL cipher specifcation. If we see a packet
|
||||
## that has bigger cipherspecs, we won't do a comparisons of cipherspecs.
|
||||
const ssl_max_cipherspec_size = 68 &redef;
|
||||
|
||||
# todo::Is this still used?
|
||||
# type X509_extensions: table[count] of string;
|
||||
|
||||
## An X509 certificate.
|
||||
##
|
||||
## .. bro:see:: x509_certificate
|
||||
|
@ -1725,10 +2036,6 @@ type X509: record {
|
|||
not_valid_after: time; ##< Timestamp after when certificate is not valid.
|
||||
};
|
||||
|
||||
# This is indexed with the CA's name and yields a DER (binary) encoded certificate.
|
||||
# todo::Is this still used?
|
||||
# const root_ca_certs: table[string] of string = {} &redef;
|
||||
|
||||
## HTTP session statistics.
|
||||
##
|
||||
## .. bro:see:: http_stats
|
||||
|
@ -2146,26 +2453,6 @@ const forward_remote_state_changes = F &redef;
|
|||
## Place-holder constant indicating "no peer".
|
||||
const PEER_ID_NONE = 0;
|
||||
|
||||
## Deprecated.
|
||||
##
|
||||
## .. todo:: The connection compressor is scheduled to be removed from Bro.
|
||||
const use_connection_compressor = F &redef;
|
||||
|
||||
## Deprecated.
|
||||
##
|
||||
## .. todo:: The connection compressor is scheduled to be removed from Bro.
|
||||
const cc_handle_resets = F &redef;
|
||||
|
||||
## Deprecated.
|
||||
##
|
||||
## .. todo:: The connection compressor is scheduled to be removed from Bro.
|
||||
const cc_handle_only_syns = T &redef;
|
||||
|
||||
## Deprecated.
|
||||
##
|
||||
## .. todo:: The connection compressor is scheduled to be removed from Bro.
|
||||
const cc_instantiate_on_data = F &redef;
|
||||
|
||||
# Signature payload pattern types.
|
||||
# todo::use enum to help autodoc
|
||||
# todo::Still used?
|
||||
|
|
|
@ -40,8 +40,6 @@ export {
|
|||
rcode: count &log &optional;
|
||||
## A descriptive name for the response code value.
|
||||
rcode_name: string &log &optional;
|
||||
## Whether the message is a query (F) or response (T).
|
||||
QR: bool &log &default=F;
|
||||
## The Authoritative Answer bit for response messages specifies that
|
||||
## the responding name server is an authority for the domain name
|
||||
## in the question section.
|
||||
|
@ -250,10 +248,13 @@ event dns_TXT_reply(c: connection, msg: dns_msg, ans: dns_answer, str: string) &
|
|||
event DNS::do_reply(c, msg, ans, str);
|
||||
}
|
||||
|
||||
event dns_AAAA_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr,
|
||||
astr: string) &priority=5
|
||||
event dns_AAAA_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, fmt("%s", a));
|
||||
}
|
||||
|
||||
event dns_A6_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) &priority=5
|
||||
{
|
||||
# TODO: What should we do with astr?
|
||||
event DNS::do_reply(c, msg, ans, fmt("%s", a));
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ export {
|
|||
const default_capture_password = F &redef;
|
||||
|
||||
## User IDs that can be considered "anonymous".
|
||||
const guest_ids = { "anonymous", "ftp", "guest" } &redef;
|
||||
const guest_ids = { "anonymous", "ftp", "ftpuser", "guest" } &redef;
|
||||
|
||||
type Info: record {
|
||||
## Time when the command was sent.
|
||||
|
@ -160,12 +160,21 @@ function ftp_message(s: Info)
|
|||
# or it's a deliberately logged command.
|
||||
if ( |s$tags| > 0 || (s?$cmdarg && s$cmdarg$cmd in logged_commands) )
|
||||
{
|
||||
if ( s?$password && to_lower(s$user) !in guest_ids )
|
||||
if ( s?$password &&
|
||||
! s$capture_password &&
|
||||
to_lower(s$user) !in guest_ids )
|
||||
{
|
||||
s$password = "<hidden>";
|
||||
}
|
||||
|
||||
local arg = s$cmdarg$arg;
|
||||
if ( s$cmdarg$cmd in file_cmds )
|
||||
{
|
||||
if ( is_v4_addr(s$id$resp_h) )
|
||||
arg = fmt("ftp://%s%s", s$id$resp_h, build_path_compressed(s$cwd, arg));
|
||||
else
|
||||
arg = fmt("ftp://[%s]%s", s$id$resp_h, build_path_compressed(s$cwd, arg));
|
||||
}
|
||||
|
||||
s$ts=s$cmdarg$ts;
|
||||
s$command=s$cmdarg$cmd;
|
||||
|
@ -270,7 +279,7 @@ event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool) &prior
|
|||
{
|
||||
c$ftp$passive=T;
|
||||
|
||||
if ( code == 229 && data$h == 0.0.0.0 )
|
||||
if ( code == 229 && data$h == [::] )
|
||||
data$h = id$resp_h;
|
||||
|
||||
ftp_data_expected[data$h, data$p] = c$ftp;
|
||||
|
|
|
@ -13,7 +13,7 @@ export {
|
|||
[TLSv10] = "TLSv10",
|
||||
[TLSv11] = "TLSv11",
|
||||
[TLSv12] = "TLSv12",
|
||||
} &default="UNKNOWN";
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
## Mapping between numeric codes and human readable strings for alert
|
||||
## levels.
|
||||
|
@ -77,7 +77,9 @@ export {
|
|||
[12] = "srp",
|
||||
[13] = "signature_algorithms",
|
||||
[14] = "use_srtp",
|
||||
[15] = "heartbeat",
|
||||
[35] = "SessionTicket TLS",
|
||||
[40] = "extended_random",
|
||||
[13172] = "next_protocol_negotiation",
|
||||
[65281] = "renegotiation_info"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
@ -535,7 +537,7 @@ export {
|
|||
[SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA] = "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA",
|
||||
[SSL_RSA_FIPS_WITH_DES_CBC_SHA_2] = "SSL_RSA_FIPS_WITH_DES_CBC_SHA_2",
|
||||
[SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA_2] = "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA_2",
|
||||
} &default="UNKNOWN";
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
## Mapping between the constants and string values for SSL/TLS errors.
|
||||
const x509_errors: table[count] of string = {
|
||||
|
@ -573,6 +575,6 @@ export {
|
|||
[31] = "keyusage no certsign",
|
||||
[32] = "unable to get crl issuer",
|
||||
[33] = "unhandled critical extension",
|
||||
};
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ event signature_match(state: signature_state, msg: string, data: string) &priori
|
|||
|
||||
local c = state$conn;
|
||||
local si = Software::Info;
|
||||
si = [$unparsed_version=msg, $host=c$id$resp_h, $host_p=c$id$resp_p, $software_type=WEB_APPLICATION];
|
||||
si = [$name=msg, $unparsed_version=msg, $host=c$id$resp_h, $host_p=c$id$resp_p, $software_type=WEB_APPLICATION];
|
||||
si$url = build_url_http(c$http);
|
||||
if ( c$id$resp_h in Software::tracked &&
|
||||
si$name in Software::tracked[c$id$resp_h] )
|
||||
|
|
|
@ -17,7 +17,7 @@ ARP_Analyzer::~ARP_Analyzer()
|
|||
{
|
||||
}
|
||||
|
||||
bool ARP_Analyzer::IsARP(const u_char* pkt, int hdr_size) const
|
||||
bool ARP_Analyzer::IsARP(const u_char* pkt, int hdr_size)
|
||||
{
|
||||
unsigned short network_protocol =
|
||||
*(unsigned short*) (pkt + hdr_size - 2);
|
||||
|
|
|
@ -31,9 +31,6 @@ public:
|
|||
ARP_Analyzer();
|
||||
virtual ~ARP_Analyzer();
|
||||
|
||||
// Whether a packet is of interest for ARP analysis.
|
||||
bool IsARP(const u_char* pkt, int hdr_size) const;
|
||||
|
||||
void NextPacket(double t, const struct pcap_pkthdr* hdr,
|
||||
const u_char* const pkt, int hdr_size);
|
||||
|
||||
|
@ -41,6 +38,10 @@ public:
|
|||
void RREvent(EventHandlerPtr e, const u_char* src, const u_char* dst,
|
||||
const char* spa, const char* sha,
|
||||
const char* tpa, const char* tha);
|
||||
|
||||
// Whether a packet is of interest for ARP analysis.
|
||||
static bool IsARP(const u_char* pkt, int hdr_size);
|
||||
|
||||
protected:
|
||||
AddrVal* ConstructAddrVal(const void* addr);
|
||||
StringVal* EthAddrToStr(const u_char* addr);
|
||||
|
|
|
@ -49,18 +49,6 @@ const Analyzer::Config Analyzer::analyzer_configs[] = {
|
|||
|
||||
{ AnalyzerTag::ICMP, "ICMP", ICMP_Analyzer::InstantiateAnalyzer,
|
||||
ICMP_Analyzer::Available, 0, false },
|
||||
{ AnalyzerTag::ICMP_TimeExceeded, "ICMP_TIMEEXCEEDED",
|
||||
ICMP_TimeExceeded_Analyzer::InstantiateAnalyzer,
|
||||
ICMP_TimeExceeded_Analyzer::Available, 0, false },
|
||||
{ AnalyzerTag::ICMP_Unreachable, "ICMP_UNREACHABLE",
|
||||
ICMP_Unreachable_Analyzer::InstantiateAnalyzer,
|
||||
ICMP_Unreachable_Analyzer::Available, 0, false },
|
||||
{ AnalyzerTag::ICMP_Echo, "ICMP_ECHO",
|
||||
ICMP_Echo_Analyzer::InstantiateAnalyzer,
|
||||
ICMP_Echo_Analyzer::Available, 0, false },
|
||||
{ AnalyzerTag::ICMP_Redir, "ICMP_REDIR",
|
||||
ICMP_Redir_Analyzer::InstantiateAnalyzer,
|
||||
ICMP_Redir_Analyzer::Available, 0, false },
|
||||
|
||||
{ AnalyzerTag::TCP, "TCP", TCP_Analyzer::InstantiateAnalyzer,
|
||||
TCP_Analyzer::Available, 0, false },
|
||||
|
|
|
@ -20,9 +20,7 @@ namespace AnalyzerTag {
|
|||
PIA_TCP, PIA_UDP,
|
||||
|
||||
// Transport-layer analyzers.
|
||||
ICMP,
|
||||
ICMP_TimeExceeded, ICMP_Unreachable, ICMP_Echo, ICMP_Redir,
|
||||
TCP, UDP,
|
||||
ICMP, TCP, UDP,
|
||||
|
||||
// Application-layer analyzers (hand-written).
|
||||
BitTorrent, BitTorrentTracker,
|
||||
|
|
|
@ -153,7 +153,9 @@ void AnonymizeIPAddr_A50::init()
|
|||
|
||||
int AnonymizeIPAddr_A50::PreservePrefix(ipaddr32_t input, int num_bits)
|
||||
{
|
||||
DEBUG_MSG("%s/%d\n", dotted_addr(input), num_bits);
|
||||
DEBUG_MSG("%s/%d\n",
|
||||
IPAddr(IPv4, &input, IPAddr::Network).AsString().c_str(),
|
||||
num_bits);
|
||||
|
||||
if ( ! before_anonymization )
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "Attr.h"
|
||||
#include "Expr.h"
|
||||
#include "Serializer.h"
|
||||
#include "LogMgr.h"
|
||||
#include "threading/SerialTypes.h"
|
||||
|
||||
const char* attr_name(attr_tag t)
|
||||
{
|
||||
|
@ -416,7 +416,7 @@ void Attributes::CheckAttr(Attr* a)
|
|||
break;
|
||||
|
||||
case ATTR_LOG:
|
||||
if ( ! LogVal::IsCompatibleType(type) )
|
||||
if ( ! threading::Value::IsCompatibleType(type) )
|
||||
Error("&log applied to a type that cannot be logged");
|
||||
break;
|
||||
|
||||
|
|
|
@ -66,39 +66,44 @@ void BitTorrent_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
|
|||
|
||||
void BitTorrent_Analyzer::Undelivered(int seq, int len, bool orig)
|
||||
{
|
||||
uint64 entry_offset = orig ?
|
||||
*interp->upflow()->next_message_offset() :
|
||||
*interp->downflow()->next_message_offset();
|
||||
uint64& this_stream_len = orig ? stream_len_orig : stream_len_resp;
|
||||
bool& this_stop = orig ? stop_orig : stop_resp;
|
||||
|
||||
TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
|
||||
|
||||
this_stream_len += len;
|
||||
// TODO: Code commented out for now. I think that shoving data that
|
||||
// is definitely wrong into the parser seems like a really bad idea.
|
||||
// The way it's currently tracking the next message offset isn't
|
||||
// compatible with new 64bit int support in binpac either.
|
||||
|
||||
if ( entry_offset < this_stream_len )
|
||||
{ // entry point is somewhere in the gap
|
||||
DeliverWeird("Stopping BitTorrent analysis: cannot recover from content gap", orig);
|
||||
this_stop = true;
|
||||
if ( stop_orig && stop_resp )
|
||||
ProtocolViolation("BitTorrent: content gap and/or protocol violation");
|
||||
}
|
||||
else
|
||||
{ // fill the gap
|
||||
try
|
||||
{
|
||||
u_char gap[len];
|
||||
memset(gap, 0, len);
|
||||
interp->NewData(orig, gap, gap + len);
|
||||
}
|
||||
catch ( binpac::Exception const &e )
|
||||
{
|
||||
DeliverWeird("Stopping BitTorrent analysis: filling content gap failed", orig);
|
||||
this_stop = true;
|
||||
if ( stop_orig && stop_resp )
|
||||
ProtocolViolation("BitTorrent: content gap and/or protocol violation");
|
||||
}
|
||||
}
|
||||
//uint64 entry_offset = orig ?
|
||||
// *interp->upflow()->next_message_offset() :
|
||||
// *interp->downflow()->next_message_offset();
|
||||
//uint64& this_stream_len = orig ? stream_len_orig : stream_len_resp;
|
||||
//bool& this_stop = orig ? stop_orig : stop_resp;
|
||||
//
|
||||
//this_stream_len += len;
|
||||
//
|
||||
//if ( entry_offset < this_stream_len )
|
||||
// { // entry point is somewhere in the gap
|
||||
// DeliverWeird("Stopping BitTorrent analysis: cannot recover from content gap", orig);
|
||||
// this_stop = true;
|
||||
// if ( stop_orig && stop_resp )
|
||||
// ProtocolViolation("BitTorrent: content gap and/or protocol violation");
|
||||
// }
|
||||
//else
|
||||
// { // fill the gap
|
||||
// try
|
||||
// {
|
||||
// u_char gap[len];
|
||||
// memset(gap, 0, len);
|
||||
// interp->NewData(orig, gap, gap + len);
|
||||
// }
|
||||
// catch ( binpac::Exception const &e )
|
||||
// {
|
||||
// DeliverWeird("Stopping BitTorrent analysis: filling content gap failed", orig);
|
||||
// this_stop = true;
|
||||
// if ( stop_orig && stop_resp )
|
||||
// ProtocolViolation("BitTorrent: content gap and/or protocol violation");
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
void BitTorrent_Analyzer::EndpointEOF(TCP_Reassembler* endp)
|
||||
|
|
|
@ -85,12 +85,13 @@ void BroDoc::AddImport(const std::string& s)
|
|||
if ( ext_pos != std::string::npos )
|
||||
lname = lname.substr(0, ext_pos);
|
||||
|
||||
const char* full_filename = "<error>";
|
||||
const char* subpath = "<error>";
|
||||
const char* full_filename = NULL;
|
||||
const char* subpath = NULL;
|
||||
|
||||
FILE* f = search_for_file(lname.c_str(), "bro", &full_filename, true,
|
||||
&subpath);
|
||||
|
||||
if ( f )
|
||||
if ( f && full_filename && subpath )
|
||||
{
|
||||
fclose(f);
|
||||
|
||||
|
@ -126,12 +127,14 @@ void BroDoc::AddImport(const std::string& s)
|
|||
}
|
||||
|
||||
delete [] tmp;
|
||||
delete [] full_filename;
|
||||
delete [] subpath;
|
||||
}
|
||||
|
||||
else
|
||||
fprintf(stderr, "Failed to document '@load %s' in file: %s\n",
|
||||
s.c_str(), reST_filename.c_str());
|
||||
|
||||
delete [] full_filename;
|
||||
delete [] subpath;
|
||||
}
|
||||
|
||||
void BroDoc::SetPacketFilter(const std::string& s)
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include "Brofiler.h"
|
||||
#include "util.h"
|
||||
|
||||
Brofiler::Brofiler()
|
||||
: delim('\t'), ignoring(0)
|
||||
: ignoring(0), delim('\t')
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -48,10 +49,27 @@ bool Brofiler::WriteStats()
|
|||
char* bf = getenv("BRO_PROFILER_FILE");
|
||||
if ( ! bf ) return false;
|
||||
|
||||
FILE* f = fopen(bf, "w");
|
||||
FILE* f;
|
||||
const char* p = strstr(bf, ".XXXXXX");
|
||||
|
||||
if ( p && ! p[7] )
|
||||
{
|
||||
int fd = mkstemp(bf);
|
||||
if ( fd == -1 )
|
||||
{
|
||||
reporter->Error("Failed to generate unique file name from BRO_PROFILER_FILE: %s", bf);
|
||||
return false;
|
||||
}
|
||||
f = fdopen(fd, "w");
|
||||
}
|
||||
else
|
||||
{
|
||||
f = fopen(bf, "w");
|
||||
}
|
||||
|
||||
if ( ! f )
|
||||
{
|
||||
reporter->Error("Failed to open BRO_PROFILER_FILE destination '%s' for writing\n", bf);
|
||||
reporter->Error("Failed to open BRO_PROFILER_FILE destination '%s' for writing", bf);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,9 @@ public:
|
|||
/**
|
||||
* Combines usage stats from current run with any read from ReadStats(),
|
||||
* then writes information to file pointed to by environment variable
|
||||
* BRO_PROFILER_FILE.
|
||||
* BRO_PROFILER_FILE. If the value of that env. variable ends with
|
||||
* ".XXXXXX" (exactly 6 X's), then it is first passed through mkstemp
|
||||
* to get a unique file.
|
||||
*
|
||||
* @return: true when usage info is written, otherwise false.
|
||||
*/
|
||||
|
|
|
@ -213,6 +213,8 @@ binpac_target(syslog.pac
|
|||
########################################################################
|
||||
## bro target
|
||||
|
||||
find_package (Threads)
|
||||
|
||||
# This macro stores associated headers for any C/C++ source files given
|
||||
# as arguments (past _var) as a list in the CMake variable named "_var".
|
||||
macro(COLLECT_HEADERS _var)
|
||||
|
@ -288,7 +290,6 @@ set(bro_SRCS
|
|||
ChunkedIO.cc
|
||||
CompHash.cc
|
||||
Conn.cc
|
||||
ConnCompressor.cc
|
||||
ConnSizeAnalyzer.cc
|
||||
ContentLine.cc
|
||||
DCE_RPC.cc
|
||||
|
@ -331,13 +332,11 @@ set(bro_SRCS
|
|||
IntSet.cc
|
||||
InterConn.cc
|
||||
IOSource.cc
|
||||
IP.cc
|
||||
IPAddr.cc
|
||||
IRC.cc
|
||||
List.cc
|
||||
Reporter.cc
|
||||
LogMgr.cc
|
||||
LogWriter.cc
|
||||
LogWriterAscii.cc
|
||||
LogWriterNone.cc
|
||||
Login.cc
|
||||
MIME.cc
|
||||
NCP.cc
|
||||
|
@ -402,6 +401,7 @@ set(bro_SRCS
|
|||
XDR.cc
|
||||
ZIP.cc
|
||||
bsd-getopt-long.c
|
||||
bro_inet_ntop.c
|
||||
cq.c
|
||||
md5.c
|
||||
patricia.c
|
||||
|
@ -409,6 +409,18 @@ set(bro_SRCS
|
|||
PacketDumper.cc
|
||||
strsep.c
|
||||
modp_numtoa.c
|
||||
|
||||
threading/BasicThread.cc
|
||||
threading/Manager.cc
|
||||
threading/MsgThread.cc
|
||||
threading/SerialTypes.cc
|
||||
|
||||
logging/Manager.cc
|
||||
logging/WriterBackend.cc
|
||||
logging/WriterFrontend.cc
|
||||
logging/writers/Ascii.cc
|
||||
logging/writers/None.cc
|
||||
|
||||
${dns_SRCS}
|
||||
${openssl_SRCS}
|
||||
)
|
||||
|
@ -421,7 +433,7 @@ add_definitions(-DBRO_BUILD_PATH="${CMAKE_CURRENT_BINARY_DIR}")
|
|||
|
||||
add_executable(bro ${bro_SRCS} ${bro_HEADERS})
|
||||
|
||||
target_link_libraries(bro ${brodeps})
|
||||
target_link_libraries(bro ${brodeps} ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
install(TARGETS bro DESTINATION bin)
|
||||
install(FILES ${INSTALL_BIF_OUTPUTS} DESTINATION ${BRO_SCRIPT_INSTALL_PATH}/base)
|
||||
|
|
|
@ -107,40 +107,18 @@ char* CompositeHash::SingleValHash(int type_check, char* kp0,
|
|||
|
||||
case TYPE_INTERNAL_ADDR:
|
||||
{
|
||||
// Use uint32 instead of int, because 'int' is not
|
||||
// guaranteed to be 32-bit.
|
||||
uint32* kp = AlignAndPadType<uint32>(kp0);
|
||||
#ifdef BROv6
|
||||
const addr_type av = v->AsAddr();
|
||||
kp[0] = av[0];
|
||||
kp[1] = av[1];
|
||||
kp[2] = av[2];
|
||||
kp[3] = av[3];
|
||||
v->AsAddr().CopyIPv6(kp);
|
||||
kp1 = reinterpret_cast<char*>(kp+4);
|
||||
#else
|
||||
*kp = v->AsAddr();
|
||||
kp1 = reinterpret_cast<char*>(kp+1);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_SUBNET:
|
||||
{
|
||||
uint32* kp = AlignAndPadType<uint32>(kp0);
|
||||
#ifdef BROv6
|
||||
const subnet_type* sv = v->AsSubNet();
|
||||
kp[0] = sv->net[0];
|
||||
kp[1] = sv->net[1];
|
||||
kp[2] = sv->net[2];
|
||||
kp[3] = sv->net[3];
|
||||
kp[4] = sv->width;
|
||||
v->AsSubNet().Prefix().CopyIPv6(kp);
|
||||
kp[4] = v->AsSubNet().Length();
|
||||
kp1 = reinterpret_cast<char*>(kp+5);
|
||||
#else
|
||||
const subnet_type* sv = v->AsSubNet();
|
||||
kp[0] = sv->net;
|
||||
kp[1] = sv->width;
|
||||
kp1 = reinterpret_cast<char*>(kp+2);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -358,26 +336,16 @@ HashKey* CompositeHash::ComputeSingletonHash(const Val* v, int type_check) const
|
|||
if ( type_check && v->Type()->InternalType() != singleton_tag )
|
||||
return 0;
|
||||
|
||||
uint32 tmp_addr;
|
||||
switch ( singleton_tag ) {
|
||||
case TYPE_INTERNAL_INT:
|
||||
case TYPE_INTERNAL_UNSIGNED:
|
||||
return new HashKey(v->ForceAsInt());
|
||||
|
||||
case TYPE_INTERNAL_ADDR:
|
||||
#ifdef BROv6
|
||||
return new HashKey(v->AsAddr(), 4);
|
||||
#else
|
||||
return new HashKey(v->AsAddr());
|
||||
#endif
|
||||
return v->AsAddr().GetHashKey();
|
||||
|
||||
case TYPE_INTERNAL_SUBNET:
|
||||
#ifdef BROv6
|
||||
return new HashKey((const uint32*) v->AsSubNet(), 5);
|
||||
#else
|
||||
return new HashKey((const uint32*) v->AsSubNet(), 2);
|
||||
|
||||
#endif
|
||||
return v->AsSubNet().GetHashKey();
|
||||
|
||||
case TYPE_INTERNAL_DOUBLE:
|
||||
return new HashKey(v->InternalDouble());
|
||||
|
@ -425,22 +393,13 @@ int CompositeHash::SingleTypeKeySize(BroType* bt, const Val* v,
|
|||
break;
|
||||
|
||||
case TYPE_INTERNAL_ADDR:
|
||||
#ifdef BROv6
|
||||
sz = SizeAlign(sz, sizeof(uint32));
|
||||
sz += sizeof(uint32) * 3; // to make a total of 4 words
|
||||
#else
|
||||
sz = SizeAlign(sz, sizeof(uint32));
|
||||
#endif
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_SUBNET:
|
||||
#ifdef BROv6
|
||||
sz = SizeAlign(sz, sizeof(uint32));
|
||||
sz += sizeof(uint32) * 4; // to make a total of 5 words
|
||||
#else
|
||||
sz = SizeAlign(sz, sizeof(uint32));
|
||||
sz += sizeof(uint32); // make room for width
|
||||
#endif
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_DOUBLE:
|
||||
|
@ -748,16 +707,13 @@ const char* CompositeHash::RecoverOneVal(const HashKey* k, const char* kp0,
|
|||
case TYPE_INTERNAL_ADDR:
|
||||
{
|
||||
const uint32* const kp = AlignType<uint32>(kp0);
|
||||
#ifdef BROv6
|
||||
const_addr_type addr_val = kp;
|
||||
kp1 = reinterpret_cast<const char*>(kp+4);
|
||||
#else
|
||||
const_addr_type addr_val = *kp;
|
||||
kp1 = reinterpret_cast<const char*>(kp+1);
|
||||
#endif
|
||||
|
||||
IPAddr addr(IPv6, kp, IPAddr::Network);
|
||||
|
||||
switch ( tag ) {
|
||||
case TYPE_ADDR:
|
||||
pval = new AddrVal(addr_val);
|
||||
pval = new AddrVal(addr);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -770,12 +726,9 @@ const char* CompositeHash::RecoverOneVal(const HashKey* k, const char* kp0,
|
|||
|
||||
case TYPE_INTERNAL_SUBNET:
|
||||
{
|
||||
const subnet_type* const kp =
|
||||
reinterpret_cast<const subnet_type*>(
|
||||
AlignType<uint32>(kp0));
|
||||
kp1 = reinterpret_cast<const char*>(kp+1);
|
||||
|
||||
pval = new SubNetVal(kp->net, kp->width);
|
||||
const uint32* const kp = AlignType<uint32>(kp0);
|
||||
kp1 = reinterpret_cast<const char*>(kp+5);
|
||||
pval = new SubNetVal(kp, kp[4]);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
56
src/Conn.cc
56
src/Conn.cc
|
@ -14,32 +14,6 @@
|
|||
#include "PIA.h"
|
||||
#include "binpac.h"
|
||||
|
||||
HashKey* ConnID::BuildConnKey() const
|
||||
{
|
||||
Key key;
|
||||
|
||||
// Lookup up connection based on canonical ordering, which is
|
||||
// the smaller of <src addr, src port> and <dst addr, dst port>
|
||||
// followed by the other.
|
||||
if ( is_one_way ||
|
||||
addr_port_canon_lt(src_addr, src_port, dst_addr, dst_port) )
|
||||
{
|
||||
copy_addr(src_addr, key.ip1);
|
||||
copy_addr(dst_addr, key.ip2);
|
||||
key.port1 = src_port;
|
||||
key.port2 = dst_port;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_addr(dst_addr, key.ip1);
|
||||
copy_addr(src_addr, key.ip2);
|
||||
key.port1 = dst_port;
|
||||
key.port2 = src_port;
|
||||
}
|
||||
|
||||
return new HashKey(&key, sizeof(key));
|
||||
}
|
||||
|
||||
void ConnectionTimer::Init(Connection* arg_conn, timer_func arg_timer,
|
||||
int arg_do_expire)
|
||||
{
|
||||
|
@ -143,8 +117,8 @@ Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id)
|
|||
key = k;
|
||||
start_time = last_time = t;
|
||||
|
||||
copy_addr(id->src_addr, orig_addr);
|
||||
copy_addr(id->dst_addr, resp_addr);
|
||||
orig_addr = id->src_addr;
|
||||
resp_addr = id->dst_addr;
|
||||
orig_port = id->src_port;
|
||||
resp_port = id->dst_port;
|
||||
proto = TRANSPORT_UNKNOWN;
|
||||
|
@ -521,7 +495,7 @@ Val* Connection::BuildVersionVal(const char* s, int len)
|
|||
return sw;
|
||||
}
|
||||
|
||||
int Connection::VersionFoundEvent(const uint32* addr, const char* s, int len,
|
||||
int Connection::VersionFoundEvent(const IPAddr& addr, const char* s, int len,
|
||||
Analyzer* analyzer)
|
||||
{
|
||||
if ( ! software_version_found && ! software_parse_error )
|
||||
|
@ -559,7 +533,7 @@ int Connection::VersionFoundEvent(const uint32* addr, const char* s, int len,
|
|||
return 1;
|
||||
}
|
||||
|
||||
int Connection::UnparsedVersionFoundEvent(const uint32* addr,
|
||||
int Connection::UnparsedVersionFoundEvent(const IPAddr& addr,
|
||||
const char* full, int len, Analyzer* analyzer)
|
||||
{
|
||||
// Skip leading white space.
|
||||
|
@ -693,10 +667,9 @@ TimerMgr* Connection::GetTimerMgr() const
|
|||
|
||||
void Connection::FlipRoles()
|
||||
{
|
||||
uint32 tmp_addr[NUM_ADDR_WORDS];
|
||||
copy_addr(resp_addr, tmp_addr);
|
||||
copy_addr(orig_addr, resp_addr);
|
||||
copy_addr(tmp_addr, orig_addr);
|
||||
IPAddr tmp_addr = resp_addr;
|
||||
orig_addr = resp_addr;
|
||||
resp_addr = tmp_addr;
|
||||
|
||||
uint32 tmp_port = resp_port;
|
||||
resp_port = orig_port;
|
||||
|
@ -752,14 +725,14 @@ void Connection::Describe(ODesc* d) const
|
|||
}
|
||||
|
||||
d->SP();
|
||||
d->Add(dotted_addr(orig_addr));
|
||||
d->Add(orig_addr);
|
||||
d->Add(":");
|
||||
d->Add(ntohs(orig_port));
|
||||
|
||||
d->SP();
|
||||
d->AddSP("->");
|
||||
|
||||
d->Add(dotted_addr(resp_addr));
|
||||
d->Add(resp_addr);
|
||||
d->Add(":");
|
||||
d->Add(ntohs(resp_port));
|
||||
|
||||
|
@ -782,8 +755,7 @@ bool Connection::DoSerialize(SerialInfo* info) const
|
|||
|
||||
// First we write the members which are needed to
|
||||
// create the HashKey.
|
||||
for ( int j = 0; j < NUM_ADDR_WORDS; ++j )
|
||||
if ( ! SERIALIZE(orig_addr[j]) || ! SERIALIZE(resp_addr[j]) )
|
||||
if ( ! SERIALIZE(orig_addr) || ! SERIALIZE(resp_addr) )
|
||||
return false;
|
||||
|
||||
if ( ! SERIALIZE(orig_port) || ! SERIALIZE(resp_port) )
|
||||
|
@ -830,21 +802,21 @@ bool Connection::DoUnserialize(UnserialInfo* info)
|
|||
|
||||
// Build the hash key first. Some of the recursive *::Unserialize()
|
||||
// functions may need it.
|
||||
for ( int i = 0; i < NUM_ADDR_WORDS; ++i )
|
||||
if ( ! UNSERIALIZE(&orig_addr[i]) || ! UNSERIALIZE(&resp_addr[i]) )
|
||||
ConnID id;
|
||||
|
||||
if ( ! UNSERIALIZE(&orig_addr) || ! UNSERIALIZE(&resp_addr) )
|
||||
goto error;
|
||||
|
||||
if ( ! UNSERIALIZE(&orig_port) || ! UNSERIALIZE(&resp_port) )
|
||||
goto error;
|
||||
|
||||
ConnID id;
|
||||
id.src_addr = orig_addr;
|
||||
id.dst_addr = resp_addr;
|
||||
// This doesn't work for ICMP. But I guess this is not really important.
|
||||
id.src_port = orig_port;
|
||||
id.dst_port = resp_port;
|
||||
id.is_one_way = 0; // ### incorrect for ICMP
|
||||
key = id.BuildConnKey();
|
||||
key = BuildConnIDHashKey(id);
|
||||
|
||||
int len;
|
||||
if ( ! UNSERIALIZE(&len) )
|
||||
|
|
84
src/Conn.h
84
src/Conn.h
|
@ -12,6 +12,7 @@
|
|||
#include "PersistenceSerializer.h"
|
||||
#include "RuleMatcher.h"
|
||||
#include "AnalyzerTags.h"
|
||||
#include "IPAddr.h"
|
||||
|
||||
class Connection;
|
||||
class ConnectionTimer;
|
||||
|
@ -32,52 +33,17 @@ typedef enum {
|
|||
typedef void (Connection::*timer_func)(double t);
|
||||
|
||||
struct ConnID {
|
||||
const uint32* src_addr;
|
||||
const uint32* dst_addr;
|
||||
IPAddr src_addr;
|
||||
IPAddr dst_addr;
|
||||
uint32 src_port;
|
||||
uint32 dst_port;
|
||||
bool is_one_way; // if true, don't canonicalize
|
||||
|
||||
// Returns a ListVal suitable for looking up a connection in
|
||||
// a hash table. addr/ports are expected to be in network order.
|
||||
// Unless is_one_way is true, the lookup sorts src and dst,
|
||||
// so src_addr/src_port and dst_addr/dst_port just have to
|
||||
// reflect the two different sides of the connection,
|
||||
// neither has to be the particular source/destination
|
||||
// or originator/responder.
|
||||
HashKey* BuildConnKey() const;
|
||||
|
||||
// The structure used internally for hashing.
|
||||
struct Key {
|
||||
uint32 ip1[NUM_ADDR_WORDS];
|
||||
uint32 ip2[NUM_ADDR_WORDS];
|
||||
uint16 port1;
|
||||
uint16 port2;
|
||||
};
|
||||
bool is_one_way; // if true, don't canonicalize order
|
||||
};
|
||||
|
||||
static inline int addr_port_canon_lt(const uint32* a1, uint32 p1,
|
||||
const uint32* a2, uint32 p2)
|
||||
static inline int addr_port_canon_lt(const IPAddr& addr1, uint32 p1,
|
||||
const IPAddr& addr2, uint32 p2)
|
||||
{
|
||||
#ifdef BROv6
|
||||
// Because it's a canonical ordering, not a strict ordering,
|
||||
// we can choose to give more weight to the least significant
|
||||
// word than to the most significant word. This matters
|
||||
// because for the common case of IPv4 addresses embedded in
|
||||
// a IPv6 address, the top three words are identical, so we can
|
||||
// save a few cycles by first testing the bottom word.
|
||||
return a1[3] < a2[3] ||
|
||||
(a1[3] == a2[3] &&
|
||||
(a1[2] < a2[2] ||
|
||||
(a1[2] == a2[2] &&
|
||||
(a1[1] < a2[1] ||
|
||||
(a1[1] == a2[1] &&
|
||||
(a1[0] < a2[0] ||
|
||||
(a1[0] == a2[0] &&
|
||||
p1 < p2)))))));
|
||||
#else
|
||||
return *a1 < *a2 || (*a1 == *a2 && p1 < p2);
|
||||
#endif
|
||||
return addr1 < addr2 || (addr1 == addr2 && p1 < p2);
|
||||
}
|
||||
|
||||
class Analyzer;
|
||||
|
@ -119,8 +85,8 @@ public:
|
|||
double LastTime() const { return last_time; }
|
||||
void SetLastTime(double t) { last_time = t; }
|
||||
|
||||
const uint32* OrigAddr() const { return orig_addr; }
|
||||
const uint32* RespAddr() const { return resp_addr; }
|
||||
const IPAddr& OrigAddr() const { return orig_addr; }
|
||||
const IPAddr& RespAddr() const { return resp_addr; }
|
||||
|
||||
uint32 OrigPort() const { return orig_port; }
|
||||
uint32 RespPort() const { return resp_port; }
|
||||
|
@ -185,11 +151,11 @@ public:
|
|||
|
||||
// Raises a software_version_found event based on the
|
||||
// given string (returns false if it's not parseable).
|
||||
int VersionFoundEvent(const uint32* addr, const char* s, int len,
|
||||
int VersionFoundEvent(const IPAddr& addr, const char* s, int len,
|
||||
Analyzer* analyzer = 0);
|
||||
|
||||
// Raises a software_unparsed_version_found event.
|
||||
int UnparsedVersionFoundEvent(const uint32* addr,
|
||||
int UnparsedVersionFoundEvent(const IPAddr& addr,
|
||||
const char* full_descr, int len, Analyzer* analyzer);
|
||||
|
||||
void Event(EventHandlerPtr f, Analyzer* analyzer, const char* name = 0);
|
||||
|
@ -273,30 +239,6 @@ public:
|
|||
// Sets the transport protocol in use.
|
||||
void SetTransport(TransportProto arg_proto) { proto = arg_proto; }
|
||||
|
||||
// If the connection compressor is activated, we need a special memory
|
||||
// layout for connections. (See ConnCompressor.h)
|
||||
void* operator new(size_t size)
|
||||
{
|
||||
if ( ! use_connection_compressor )
|
||||
return ::operator new(size);
|
||||
|
||||
void* c = ::operator new(size + 4);
|
||||
|
||||
// We have to turn off the is_pending bit. By setting the
|
||||
// first four bytes to zero, we'll achieve this.
|
||||
*((uint32*) c) = 0;
|
||||
|
||||
return ((char *) c) + 4;
|
||||
}
|
||||
|
||||
void operator delete(void* ptr)
|
||||
{
|
||||
if ( ! use_connection_compressor )
|
||||
::operator delete(ptr);
|
||||
else
|
||||
::operator delete(((char*) ptr) - 4);
|
||||
}
|
||||
|
||||
void SetUID(uint64 arg_uid) { uid = arg_uid; }
|
||||
|
||||
protected:
|
||||
|
@ -325,8 +267,8 @@ protected:
|
|||
TimerMgr::Tag* conn_timer_mgr;
|
||||
timer_list timers;
|
||||
|
||||
uint32 orig_addr[NUM_ADDR_WORDS]; // in network order
|
||||
uint32 resp_addr[NUM_ADDR_WORDS]; // in network order
|
||||
IPAddr orig_addr;
|
||||
IPAddr resp_addr;
|
||||
uint32 orig_port, resp_port; // in network order
|
||||
TransportProto proto;
|
||||
double start_time, last_time;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,235 +0,0 @@
|
|||
// The ConnCompressor keeps track of the first packet seen for a conn_id using
|
||||
// only a minimal amount of memory. This helps us to avoid instantiating
|
||||
// full Connection objects for never-established sessions.
|
||||
//
|
||||
// TCP only.
|
||||
|
||||
#ifndef CONNCOMPRESSOR_H
|
||||
#define CONNCOMPRESSOR_H
|
||||
|
||||
#include "Conn.h"
|
||||
#include "Dict.h"
|
||||
#include "NetVar.h"
|
||||
#include "TCP.h"
|
||||
|
||||
class ConnCompressor {
|
||||
public:
|
||||
ConnCompressor();
|
||||
~ConnCompressor();
|
||||
|
||||
// Handle next packet. Returns 0 if packet in handled internally.
|
||||
// Takes ownership of key.
|
||||
Connection* NextPacket(double t, HashKey* k, const IP_Hdr* ip_hdr,
|
||||
const struct pcap_pkthdr* hdr, const u_char* const pkt);
|
||||
|
||||
// Look up a connection. Returns non-nil for connections for
|
||||
// which a Connection object has already been instantiated.
|
||||
Connection* Lookup(HashKey* k)
|
||||
{
|
||||
ConnData* c = conns.Lookup(k);
|
||||
return c && IsConnPtr(c) ? MakeConnPtr(c) : 0;
|
||||
}
|
||||
|
||||
// Inserts connection into compressor. If another entry with this key
|
||||
// already exists, it's replaced. If that was a full connection, it is
|
||||
// also returned.
|
||||
Connection* Insert(Connection* c);
|
||||
|
||||
// Remove all state belonging to the given connection. Returns
|
||||
// true if the connection was found in the compressor's table,
|
||||
// false if not.
|
||||
bool Remove(HashKey* k);
|
||||
|
||||
// Flush state.
|
||||
void Drain();
|
||||
|
||||
struct Sizes {
|
||||
// Current number of already fully instantiated connections.
|
||||
unsigned int connections;
|
||||
|
||||
// Total number of fully instantiated connections.
|
||||
unsigned int connections_total;
|
||||
|
||||
// Current number of seen but non-yet instantiated connections.
|
||||
unsigned int pending_valid;
|
||||
|
||||
// Total number of seen but non-yet instantiated connections.
|
||||
unsigned int pending_total;
|
||||
|
||||
// Total number of all entries in pending list (some a which
|
||||
// may already been invalid, but not yet removed from memory).
|
||||
unsigned int pending_in_mem;
|
||||
|
||||
// Total number of hash table entires
|
||||
// (should equal connections + pending_valid)
|
||||
unsigned int hash_table_size;
|
||||
|
||||
// Total memory usage;
|
||||
unsigned int memory;
|
||||
};
|
||||
|
||||
const Sizes& Size()
|
||||
{ sizes.hash_table_size = conns.Length(); return sizes; }
|
||||
|
||||
unsigned int MemoryAllocation() const { return sizes.memory; }
|
||||
|
||||
// As long as we have only seen packets from one side, we just
|
||||
// store a PendingConn.
|
||||
struct PendingConn {
|
||||
// True if the block is indeed a PendingConn (see below).
|
||||
unsigned int is_pending:1;
|
||||
|
||||
// Whether roles in key are flipped.
|
||||
unsigned int ip1_is_src:1;
|
||||
|
||||
unsigned int invalid:1; // deleted
|
||||
int window_scale:4;
|
||||
unsigned int SYN:1;
|
||||
unsigned int FIN:1;
|
||||
unsigned int RST:1;
|
||||
unsigned int ACK:1;
|
||||
|
||||
double time;
|
||||
ConnID::Key key;
|
||||
uint32 seq;
|
||||
uint32 ack;
|
||||
hash_t hash;
|
||||
uint16 window;
|
||||
uint64 uid;
|
||||
|
||||
// The following are set if use_conn_size_analyzer is T.
|
||||
uint16 num_pkts;
|
||||
uint16 num_bytes_ip;
|
||||
};
|
||||
|
||||
private:
|
||||
// Helpers to extract addrs/ports from PendingConn.
|
||||
|
||||
const uint32* SrcAddr(const PendingConn* c)
|
||||
{ return c->ip1_is_src ? c->key.ip1 : c->key.ip2; }
|
||||
const uint32* DstAddr(const PendingConn* c)
|
||||
{ return c->ip1_is_src ? c->key.ip2 : c->key.ip1; }
|
||||
|
||||
uint16 SrcPort(const PendingConn* c)
|
||||
{ return c->ip1_is_src ? c->key.port1 : c->key.port2; }
|
||||
uint16 DstPort(const PendingConn* c)
|
||||
{ return c->ip1_is_src ? c->key.port2 : c->key.port1; }
|
||||
|
||||
|
||||
// Called for the first packet in a connection.
|
||||
Connection* FirstFromOrig(double t, HashKey* key,
|
||||
const IP_Hdr* ip, const tcphdr* tp);
|
||||
|
||||
// Called for more packets from the orginator w/o seeing a response.
|
||||
Connection* NextFromOrig(PendingConn* pending, double t, HashKey* key,
|
||||
const IP_Hdr* ip, const tcphdr* tp);
|
||||
|
||||
// Called for the first response packet. Instantiates a Connection.
|
||||
Connection* Response(PendingConn* pending, double t, HashKey* key,
|
||||
const IP_Hdr* ip, const tcphdr* tp);
|
||||
|
||||
// Instantiates a full TCP connection (invalidates pending connection).
|
||||
Connection* Instantiate(HashKey* key, PendingConn* pending);
|
||||
|
||||
// Same but based on packet.
|
||||
Connection* Instantiate(double t, HashKey* key, const IP_Hdr* ip);
|
||||
|
||||
// Fills the attributes of a PendingConn based on the given arguments.
|
||||
void PktHdrToPendingConn(double time, const HashKey* key,
|
||||
const IP_Hdr* ip, const struct tcphdr* tp, PendingConn* c);
|
||||
|
||||
// Fakes a TCP packet based on the available information.
|
||||
const IP_Hdr* PendingConnToPacket(const PendingConn* c);
|
||||
|
||||
// Construct a TCP-flags byte.
|
||||
uint8 MakeFlags(const PendingConn* c) const;
|
||||
|
||||
// Allocate room for a new (Ext)PendingConn.
|
||||
PendingConn* MakeNewState(double t);
|
||||
|
||||
// Expire PendingConns.
|
||||
void DoExpire(double t);
|
||||
|
||||
// Remove all state belonging to the given connection.
|
||||
void Invalidate(HashKey* k);
|
||||
|
||||
// Sends the given connection_* event. If orig_state is
|
||||
// TCP_ENDPOINT__INACTIVE, tries to guess a better one based
|
||||
// on pending. If arg in non-nil, it will be used as the
|
||||
// *first* argument of the event call (this is for conn_weird()).
|
||||
void Event(const PendingConn* pending, double t,
|
||||
const EventHandlerPtr& event, int orig_state,
|
||||
int orig_size, int resp_state, Val* arg = 0);
|
||||
|
||||
void Weird(const PendingConn* pending, double t, const char* msg)
|
||||
{
|
||||
// This will actually go through the Reporter; Event() takes
|
||||
// care of that.
|
||||
Event(pending, t, conn_weird, TCP_ENDPOINT_INACTIVE, 0,
|
||||
TCP_ENDPOINT_INACTIVE, new StringVal(msg));
|
||||
}
|
||||
|
||||
static const int BLOCK_SIZE = 16 * 1024;
|
||||
|
||||
// The memory managment for PendConns.
|
||||
struct Block {
|
||||
double time;
|
||||
Block* prev;
|
||||
Block* next;
|
||||
int bytes_used;
|
||||
unsigned char data[BLOCK_SIZE];
|
||||
};
|
||||
|
||||
// In the connection hash table, we store pointers to both PendingConns
|
||||
// and Connections. Thus, we need a way to differentiate between
|
||||
// these two types. To avoid an additional indirection, we use a little
|
||||
// hack: a pointer retrieved from the table is interpreted as a
|
||||
// PendingConn first. However, if is_pending is false, it's in fact a
|
||||
// Connection which starts at offset 4. The methods below help to
|
||||
// implement this scheme transparently. An "operator new" in
|
||||
// Connection takes care of building Connection's accordingly.
|
||||
typedef PendingConn ConnData;
|
||||
declare(PDict, ConnData);
|
||||
typedef PDict(ConnData) ConnMap;
|
||||
ConnMap conns;
|
||||
|
||||
static ConnData* MakeMapPtr(PendingConn* c)
|
||||
{ assert(c->is_pending); return c; }
|
||||
|
||||
static ConnData* MakeMapPtr(Connection* c)
|
||||
{
|
||||
ConnData* p = (ConnData*) (((char*) c) - 4);
|
||||
assert(!p->is_pending);
|
||||
return p;
|
||||
}
|
||||
|
||||
static PendingConn* MakePendingConnPtr(ConnData* c)
|
||||
{ assert(c->is_pending); return c; }
|
||||
|
||||
static Connection* MakeConnPtr(ConnData* c)
|
||||
{
|
||||
assert(!c->is_pending);
|
||||
return (Connection*) (((char*) c) + 4);
|
||||
}
|
||||
|
||||
static bool IsConnPtr(ConnData* c)
|
||||
{ return ! c->is_pending; }
|
||||
|
||||
// New blocks are inserted at the end.
|
||||
Block* first_block;
|
||||
Block* last_block;
|
||||
|
||||
// If we have already expired some entries in a block,
|
||||
// this points to the first non-expired.
|
||||
unsigned char* first_non_expired;
|
||||
|
||||
// Last "connection" that we have build.
|
||||
RecordVal* conn_val;
|
||||
|
||||
// Statistics.
|
||||
Sizes sizes;
|
||||
};
|
||||
|
||||
extern ConnCompressor* conn_compressor;
|
||||
|
||||
#endif
|
|
@ -137,12 +137,12 @@ static bool is_mapped_dce_rpc_endpoint(const dce_rpc_endpoint_addr& addr)
|
|||
|
||||
bool is_mapped_dce_rpc_endpoint(const ConnID* id, TransportProto proto)
|
||||
{
|
||||
#ifdef BROv6
|
||||
if ( ! is_v4_addr(id->dst_addr) )
|
||||
if ( id->dst_addr.GetFamily() == IPv6 )
|
||||
// TODO: Does the protocol support v6 addresses? #773
|
||||
return false;
|
||||
#endif
|
||||
|
||||
dce_rpc_endpoint_addr addr;
|
||||
addr.addr = ntohl(to_v4_addr(id->dst_addr));
|
||||
addr.addr = id->dst_addr;
|
||||
addr.port = ntohs(id->dst_port);
|
||||
addr.proto = proto;
|
||||
|
||||
|
@ -160,12 +160,7 @@ static void add_dce_rpc_endpoint(const dce_rpc_endpoint_addr& addr,
|
|||
// of the dce_rpc_endpoints table.
|
||||
// FIXME: Don't hard-code the timeout.
|
||||
|
||||
// Convert the address to a v4/v6 address (depending on how
|
||||
// Bro was configured). This is all based on the address currently
|
||||
// being a 32-bit host-order v4 address.
|
||||
AddrVal a(htonl(addr.addr));
|
||||
const addr_type at = a.AsAddr();
|
||||
dpm->ExpectConnection(0, at, addr.port, addr.proto,
|
||||
dpm->ExpectConnection(IPAddr(), addr.addr, addr.port, addr.proto,
|
||||
AnalyzerTag::DCE_RPC, 5 * 60, 0);
|
||||
}
|
||||
|
||||
|
@ -418,8 +413,8 @@ void DCE_RPC_Session::DeliverEpmapperMapResponse(
|
|||
break;
|
||||
|
||||
case binpac::DCE_RPC_Simple::EPM_PROTOCOL_IP:
|
||||
mapped.addr.addr =
|
||||
floor->rhs()->data()->ip();
|
||||
uint32 hostip = floor->rhs()->data()->ip();
|
||||
mapped.addr.addr = IPAddr(IPv4, &hostip, IPAddr::Host);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -433,7 +428,7 @@ void DCE_RPC_Session::DeliverEpmapperMapResponse(
|
|||
vl->append(analyzer->BuildConnVal());
|
||||
vl->append(new StringVal(mapped.uuid.to_string()));
|
||||
vl->append(new PortVal(mapped.addr.port, mapped.addr.proto));
|
||||
vl->append(new AddrVal(htonl(mapped.addr.addr)));
|
||||
vl->append(new AddrVal(mapped.addr.addr));
|
||||
|
||||
analyzer->ConnectionEvent(epm_map_response, vl);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "NetVar.h"
|
||||
#include "TCP.h"
|
||||
#include "IPAddr.h"
|
||||
|
||||
#include "dce_rpc_simple_pac.h"
|
||||
|
||||
|
@ -34,19 +35,19 @@ const char* uuid_to_string(const u_char* uuid_data);
|
|||
|
||||
struct dce_rpc_endpoint_addr {
|
||||
// All fields are in host byteorder.
|
||||
uint32 addr;
|
||||
IPAddr addr;
|
||||
u_short port;
|
||||
TransportProto proto;
|
||||
|
||||
dce_rpc_endpoint_addr()
|
||||
{
|
||||
addr = 0;
|
||||
addr = IPAddr();
|
||||
port = 0;
|
||||
proto = TRANSPORT_UNKNOWN;
|
||||
}
|
||||
|
||||
bool is_valid_addr() const
|
||||
{ return addr != 0 && port != 0 && proto != TRANSPORT_UNKNOWN; }
|
||||
{ return addr != IPAddr() && port != 0 && proto != TRANSPORT_UNKNOWN; }
|
||||
|
||||
bool operator<(dce_rpc_endpoint_addr const &e) const
|
||||
{
|
||||
|
@ -64,7 +65,7 @@ struct dce_rpc_endpoint_addr {
|
|||
{
|
||||
static char buf[128];
|
||||
snprintf(buf, sizeof(buf), "%s/%d/%s",
|
||||
dotted_addr(htonl(addr)), port,
|
||||
addr.AsString().c_str(), port,
|
||||
proto == TRANSPORT_TCP ? "tcp" :
|
||||
(proto == TRANSPORT_UDP ? "udp" : "?"));
|
||||
|
||||
|
|
49
src/DNS.cc
49
src/DNS.cc
|
@ -758,62 +758,37 @@ int DNS_Interpreter::ParseRR_A(DNS_MsgInfo* msg,
|
|||
int DNS_Interpreter::ParseRR_AAAA(DNS_MsgInfo* msg,
|
||||
const u_char*& data, int& len, int rdlength)
|
||||
{
|
||||
// We need to parse an IPv6 address, high-order byte first.
|
||||
// ### Currently, we fake an A reply rather than an AAAA reply,
|
||||
// since for the latter we won't be able to express the full
|
||||
// address (unless Bro was compiled for IPv6 addresses). We do
|
||||
// this fake by using just the bottom 4 bytes of the IPv6 address.
|
||||
uint32 addr[4];
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < 4; ++i )
|
||||
for ( int i = 0; i < 4; ++i )
|
||||
{
|
||||
addr[i] = ntohl(ExtractLong(data, len));
|
||||
addr[i] = htonl(ExtractLong(data, len));
|
||||
|
||||
if ( len < 0 )
|
||||
{
|
||||
if ( msg->atype == TYPE_AAAA )
|
||||
analyzer->Weird("DNS_AAAA_neg_length");
|
||||
else
|
||||
analyzer->Weird("DNS_A6_neg_length");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Currently, dns_AAAA_reply is treated like dns_A_reply, since
|
||||
// IPv6 addresses are not generally processed. This needs to be
|
||||
// fixed. ###
|
||||
if ( dns_A_reply && ! msg->skip_event )
|
||||
EventHandlerPtr event;
|
||||
if ( msg->atype == TYPE_AAAA )
|
||||
event = dns_AAAA_reply;
|
||||
else
|
||||
event = dns_A6_reply;
|
||||
if ( event && ! msg->skip_event )
|
||||
{
|
||||
val_list* vl = new val_list;
|
||||
|
||||
vl->append(analyzer->BuildConnVal());
|
||||
vl->append(msg->BuildHdrVal());
|
||||
vl->append(msg->BuildAnswerVal());
|
||||
vl->append(new AddrVal(htonl(addr[3])));
|
||||
|
||||
analyzer->ConnectionEvent(dns_A_reply, vl);
|
||||
}
|
||||
|
||||
#if 0
|
||||
alternative AAAA code from Chris
|
||||
if ( dns_AAAA_reply && ! msg->skip_event )
|
||||
{
|
||||
val_list* vl = new val_list;
|
||||
|
||||
vl->append(analyzer->BuildConnVal());
|
||||
vl->append(msg->BuildHdrVal());
|
||||
vl->append(msg->BuildAnswerVal());
|
||||
#ifdef BROv6
|
||||
// FIXME: might need to htonl the addr first
|
||||
vl->append(new AddrVal(addr));
|
||||
#else
|
||||
vl->append(new AddrVal((uint32)0x0000));
|
||||
#endif
|
||||
char addrstr[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, addr, addrstr, INET6_ADDRSTRLEN);
|
||||
vl->append(new StringVal(addrstr));
|
||||
|
||||
analyzer->ConnectionEvent(dns_AAAA_reply, vl);
|
||||
analyzer->ConnectionEvent(event, vl);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
310
src/DNS_Mgr.cc
310
src/DNS_Mgr.cc
|
@ -46,13 +46,13 @@ extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
|
|||
|
||||
class DNS_Mgr_Request {
|
||||
public:
|
||||
DNS_Mgr_Request(const char* h) { host = copy_string(h); addr = 0; }
|
||||
DNS_Mgr_Request(uint32 a) { addr = a; host = 0; }
|
||||
DNS_Mgr_Request(const char* h, int af) { host = copy_string(h); fam = af; }
|
||||
DNS_Mgr_Request(const IPAddr& a) { addr = a; host = 0; fam = 0; }
|
||||
~DNS_Mgr_Request() { delete [] host; }
|
||||
|
||||
// Returns nil if this was an address request.
|
||||
const char* ReqHost() const { return host; }
|
||||
uint32 ReqAddr() const { return addr; }
|
||||
const IPAddr& ReqAddr() const { return addr; }
|
||||
|
||||
int MakeRequest(nb_dns_info* nb_dns);
|
||||
int RequestPending() const { return request_pending; }
|
||||
|
@ -61,8 +61,8 @@ public:
|
|||
|
||||
protected:
|
||||
char* host; // if non-nil, this is a host request
|
||||
uint32 addr;
|
||||
uint32 ttl;
|
||||
int fam; // address family query type for host requests
|
||||
IPAddr addr;
|
||||
int request_pending;
|
||||
};
|
||||
|
||||
|
@ -75,15 +75,20 @@ int DNS_Mgr_Request::MakeRequest(nb_dns_info* nb_dns)
|
|||
|
||||
char err[NB_DNS_ERRSIZE];
|
||||
if ( host )
|
||||
return nb_dns_host_request(nb_dns, host, (void*) this, err) >= 0;
|
||||
return nb_dns_host_request2(nb_dns, host, fam, (void*) this, err) >= 0;
|
||||
else
|
||||
return nb_dns_addr_request(nb_dns, addr, (void*) this, err) >= 0;
|
||||
{
|
||||
const uint32* bytes;
|
||||
int len = addr.GetBytes(&bytes);
|
||||
return nb_dns_addr_request2(nb_dns, (char*) bytes,
|
||||
len == 1 ? AF_INET : AF_INET6, (void*) this, err) >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
class DNS_Mapping {
|
||||
public:
|
||||
DNS_Mapping(const char* host, struct hostent* h, uint32 ttl);
|
||||
DNS_Mapping(uint32 addr, struct hostent* h, uint32 ttl);
|
||||
DNS_Mapping(const IPAddr& addr, struct hostent* h, uint32 ttl);
|
||||
DNS_Mapping(FILE* f);
|
||||
|
||||
int NoMapping() const { return no_mapping; }
|
||||
|
@ -93,9 +98,11 @@ public:
|
|||
|
||||
// Returns nil if this was an address request.
|
||||
const char* ReqHost() const { return req_host; }
|
||||
uint32 ReqAddr() const { return req_addr; }
|
||||
const char* ReqStr() const
|
||||
{ return req_host ? req_host : dotted_addr(ReqAddr()); }
|
||||
IPAddr ReqAddr() const { return req_addr; }
|
||||
string ReqStr() const
|
||||
{
|
||||
return req_host ? req_host : req_addr;
|
||||
}
|
||||
|
||||
ListVal* Addrs();
|
||||
TableVal* AddrsSet(); // addresses returned as a set
|
||||
|
@ -109,7 +116,14 @@ public:
|
|||
int Valid() const { return ! failed; }
|
||||
|
||||
bool Expired() const
|
||||
{ return current_time() > (creation_time + req_ttl); }
|
||||
{
|
||||
if ( req_host && num_addrs == 0)
|
||||
return false; // nothing to expire
|
||||
|
||||
return current_time() > (creation_time + req_ttl);
|
||||
}
|
||||
|
||||
int Type() const { return map_type; }
|
||||
|
||||
protected:
|
||||
friend class DNS_Mgr;
|
||||
|
@ -121,7 +135,7 @@ protected:
|
|||
int init_failed;
|
||||
|
||||
char* req_host;
|
||||
uint32 req_addr;
|
||||
IPAddr req_addr;
|
||||
uint32 req_ttl;
|
||||
|
||||
int num_names;
|
||||
|
@ -129,11 +143,12 @@ protected:
|
|||
StringVal* host_val;
|
||||
|
||||
int num_addrs;
|
||||
uint32* addrs;
|
||||
IPAddr* addrs;
|
||||
ListVal* addrs_val;
|
||||
|
||||
int failed;
|
||||
double creation_time;
|
||||
int map_type;
|
||||
};
|
||||
|
||||
void DNS_Mgr_mapping_delete_func(void* v)
|
||||
|
@ -154,14 +169,13 @@ DNS_Mapping::DNS_Mapping(const char* host, struct hostent* h, uint32 ttl)
|
|||
{
|
||||
Init(h);
|
||||
req_host = copy_string(host);
|
||||
req_addr = 0;
|
||||
req_ttl = ttl;
|
||||
|
||||
if ( names && ! names[0] )
|
||||
names[0] = copy_string(host);
|
||||
}
|
||||
|
||||
DNS_Mapping::DNS_Mapping(uint32 addr, struct hostent* h, uint32 ttl)
|
||||
DNS_Mapping::DNS_Mapping(const IPAddr& addr, struct hostent* h, uint32 ttl)
|
||||
{
|
||||
Init(h);
|
||||
req_addr = addr;
|
||||
|
@ -175,7 +189,6 @@ DNS_Mapping::DNS_Mapping(FILE* f)
|
|||
init_failed = 1;
|
||||
|
||||
req_host = 0;
|
||||
req_addr = 0;
|
||||
|
||||
char buf[512];
|
||||
|
||||
|
@ -188,14 +201,15 @@ DNS_Mapping::DNS_Mapping(FILE* f)
|
|||
char req_buf[512+1], name_buf[512+1];
|
||||
int is_req_host;
|
||||
|
||||
if ( sscanf(buf, "%lf %d %512s %d %512s %d", &creation_time, &is_req_host,
|
||||
req_buf, &failed, name_buf, &num_addrs) != 6 )
|
||||
if ( sscanf(buf, "%lf %d %512s %d %512s %d %d %"PRIu32, &creation_time,
|
||||
&is_req_host, req_buf, &failed, name_buf, &map_type, &num_addrs,
|
||||
&req_ttl) != 8 )
|
||||
return;
|
||||
|
||||
if ( is_req_host )
|
||||
req_host = copy_string(req_buf);
|
||||
else
|
||||
req_addr = dotted_to_addr(req_buf);
|
||||
req_addr = IPAddr(req_buf);
|
||||
|
||||
num_names = 1;
|
||||
names = new char*[num_names];
|
||||
|
@ -203,7 +217,7 @@ DNS_Mapping::DNS_Mapping(FILE* f)
|
|||
|
||||
if ( num_addrs > 0 )
|
||||
{
|
||||
addrs = new uint32[num_addrs];
|
||||
addrs = new IPAddr[num_addrs];
|
||||
|
||||
for ( int i = 0; i < num_addrs; ++i )
|
||||
{
|
||||
|
@ -217,7 +231,7 @@ DNS_Mapping::DNS_Mapping(FILE* f)
|
|||
if ( newline )
|
||||
*newline = '\0';
|
||||
|
||||
addrs[i] = dotted_to_addr(buf);
|
||||
addrs[i] = IPAddr(buf);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -280,14 +294,6 @@ StringVal* DNS_Mapping::Host()
|
|||
return host_val;
|
||||
}
|
||||
|
||||
// Converts an array of 4 bytes in network order to the corresponding
|
||||
// 32-bit network long.
|
||||
static uint32 raw_bytes_to_addr(const unsigned char b[4])
|
||||
{
|
||||
uint32 l = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
|
||||
return uint32(htonl(l));
|
||||
}
|
||||
|
||||
void DNS_Mapping::Init(struct hostent* h)
|
||||
{
|
||||
no_mapping = 0;
|
||||
|
@ -296,12 +302,13 @@ void DNS_Mapping::Init(struct hostent* h)
|
|||
host_val = 0;
|
||||
addrs_val = 0;
|
||||
|
||||
if ( ! h || h->h_addrtype != AF_INET || h->h_length != 4 )
|
||||
if ( ! h )
|
||||
{
|
||||
Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
map_type = h->h_addrtype;
|
||||
num_names = 1; // for now, just use official name
|
||||
names = new char*[num_names];
|
||||
names[0] = h->h_name ? copy_string(h->h_name) : 0;
|
||||
|
@ -311,10 +318,14 @@ void DNS_Mapping::Init(struct hostent* h)
|
|||
|
||||
if ( num_addrs > 0 )
|
||||
{
|
||||
addrs = new uint32[num_addrs];
|
||||
addrs = new IPAddr[num_addrs];
|
||||
for ( int i = 0; i < num_addrs; ++i )
|
||||
addrs[i] = raw_bytes_to_addr(
|
||||
(unsigned char*)h->h_addr_list[i]);
|
||||
if ( h->h_addrtype == AF_INET )
|
||||
addrs[i] = IPAddr(IPv4, (uint32*)h->h_addr_list[i],
|
||||
IPAddr::Network);
|
||||
else if ( h->h_addrtype == AF_INET6 )
|
||||
addrs[i] = IPAddr(IPv6, (uint32*)h->h_addr_list[i],
|
||||
IPAddr::Network);
|
||||
}
|
||||
else
|
||||
addrs = 0;
|
||||
|
@ -330,18 +341,19 @@ void DNS_Mapping::Clear()
|
|||
host_val = 0;
|
||||
addrs_val = 0;
|
||||
no_mapping = 0;
|
||||
map_type = 0;
|
||||
failed = 1;
|
||||
}
|
||||
|
||||
void DNS_Mapping::Save(FILE* f) const
|
||||
{
|
||||
fprintf(f, "%.0f %d %s %d %s %d\n", creation_time, req_host != 0,
|
||||
req_host ? req_host : dotted_addr(req_addr),
|
||||
fprintf(f, "%.0f %d %s %d %s %d %d %"PRIu32"\n", creation_time, req_host != 0,
|
||||
req_host ? req_host : req_addr.AsString().c_str(),
|
||||
failed, (names && names[0]) ? names[0] : "*",
|
||||
num_addrs);
|
||||
map_type, num_addrs, req_ttl);
|
||||
|
||||
for ( int i = 0; i < num_addrs; ++i )
|
||||
fprintf(f, "%s\n", dotted_addr(addrs[i]));
|
||||
fprintf(f, "%s\n", addrs[i].AsString().c_str());
|
||||
}
|
||||
|
||||
|
||||
|
@ -351,9 +363,6 @@ DNS_Mgr::DNS_Mgr(DNS_MgrMode arg_mode)
|
|||
|
||||
mode = arg_mode;
|
||||
|
||||
host_mappings.SetDeleteFunc(DNS_Mgr_mapping_delete_func);
|
||||
addr_mappings.SetDeleteFunc(DNS_Mgr_mapping_delete_func);
|
||||
|
||||
char err[NB_DNS_ERRSIZE];
|
||||
nb_dns = nb_dns_init(err);
|
||||
|
||||
|
@ -440,24 +449,34 @@ TableVal* DNS_Mgr::LookupHost(const char* name)
|
|||
|
||||
if ( mode != DNS_PRIME )
|
||||
{
|
||||
DNS_Mapping* d = host_mappings.Lookup(name);
|
||||
HostMap::iterator it = host_mappings.find(name);
|
||||
|
||||
if ( d )
|
||||
if ( it != host_mappings.end() )
|
||||
{
|
||||
if ( d->Valid() )
|
||||
return d->Addrs()->ConvertToSet();
|
||||
else
|
||||
DNS_Mapping* d4 = it->second.first;
|
||||
DNS_Mapping* d6 = it->second.second;
|
||||
|
||||
if ( (d4 && d4->Failed()) || (d6 && d6->Failed()) )
|
||||
{
|
||||
reporter->Warning("no such host: %s", name);
|
||||
return empty_addr_set();
|
||||
}
|
||||
else if ( d4 && d6 )
|
||||
{
|
||||
TableVal* tv4 = d4->AddrsSet();
|
||||
TableVal* tv6 = d6->AddrsSet();
|
||||
tv4->AddTo(tv6, false);
|
||||
Unref(tv4);
|
||||
return tv6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not found, or priming.
|
||||
switch ( mode ) {
|
||||
case DNS_PRIME:
|
||||
requests.append(new DNS_Mgr_Request(name));
|
||||
requests.append(new DNS_Mgr_Request(name, AF_INET));
|
||||
requests.append(new DNS_Mgr_Request(name, AF_INET6));
|
||||
return empty_addr_set();
|
||||
|
||||
case DNS_FORCE:
|
||||
|
@ -465,7 +484,8 @@ TableVal* DNS_Mgr::LookupHost(const char* name)
|
|||
return 0;
|
||||
|
||||
case DNS_DEFAULT:
|
||||
requests.append(new DNS_Mgr_Request(name));
|
||||
requests.append(new DNS_Mgr_Request(name, AF_INET));
|
||||
requests.append(new DNS_Mgr_Request(name, AF_INET6));
|
||||
Resolve();
|
||||
return LookupHost(name);
|
||||
|
||||
|
@ -475,24 +495,25 @@ TableVal* DNS_Mgr::LookupHost(const char* name)
|
|||
}
|
||||
}
|
||||
|
||||
Val* DNS_Mgr::LookupAddr(uint32 addr)
|
||||
Val* DNS_Mgr::LookupAddr(const IPAddr& addr)
|
||||
{
|
||||
if ( ! did_init )
|
||||
Init();
|
||||
|
||||
if ( mode != DNS_PRIME )
|
||||
{
|
||||
HashKey h(&addr, 1);
|
||||
DNS_Mapping* d = addr_mappings.Lookup(&h);
|
||||
AddrMap::iterator it = addr_mappings.find(addr);
|
||||
|
||||
if ( d )
|
||||
if ( it != addr_mappings.end() )
|
||||
{
|
||||
DNS_Mapping* d = it->second;
|
||||
if ( d->Valid() )
|
||||
return d->Host();
|
||||
else
|
||||
{
|
||||
reporter->Warning("can't resolve IP address: %s", dotted_addr(addr));
|
||||
return new StringVal(dotted_addr(addr));
|
||||
string s(addr);
|
||||
reporter->Warning("can't resolve IP address: %s", s.c_str());
|
||||
return new StringVal(s.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -505,7 +526,7 @@ Val* DNS_Mgr::LookupAddr(uint32 addr)
|
|||
|
||||
case DNS_FORCE:
|
||||
reporter->FatalError("can't find DNS entry for %s in cache",
|
||||
dotted_addr(addr));
|
||||
addr.AsString().c_str());
|
||||
return 0;
|
||||
|
||||
case DNS_DEFAULT:
|
||||
|
@ -681,28 +702,53 @@ void DNS_Mgr::AddResult(DNS_Mgr_Request* dr, struct nb_dns_result* r)
|
|||
if ( dr->ReqHost() )
|
||||
{
|
||||
new_dm = new DNS_Mapping(dr->ReqHost(), h, ttl);
|
||||
prev_dm = host_mappings.Insert(dr->ReqHost(), new_dm);
|
||||
prev_dm = 0;
|
||||
|
||||
HostMap::iterator it = host_mappings.find(dr->ReqHost());
|
||||
if ( it == host_mappings.end() )
|
||||
{
|
||||
host_mappings[dr->ReqHost()].first =
|
||||
new_dm->Type() == AF_INET ? new_dm : 0;
|
||||
host_mappings[dr->ReqHost()].second =
|
||||
new_dm->Type() == AF_INET ? 0 : new_dm;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if ( new_dm->Type() == AF_INET )
|
||||
{
|
||||
prev_dm = it->second.first;
|
||||
it->second.first = new_dm;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_dm = it->second.second;
|
||||
it->second.second = new_dm;
|
||||
}
|
||||
}
|
||||
|
||||
if ( new_dm->Failed() && prev_dm && prev_dm->Valid() )
|
||||
{
|
||||
// Put previous, valid entry back - CompareMappings
|
||||
// will generate a corresponding warning.
|
||||
(void) host_mappings.Insert(dr->ReqHost(), prev_dm);
|
||||
if ( prev_dm->Type() == AF_INET )
|
||||
host_mappings[dr->ReqHost()].first = prev_dm;
|
||||
else
|
||||
host_mappings[dr->ReqHost()].second = prev_dm;
|
||||
|
||||
++keep_prev;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new_dm = new DNS_Mapping(dr->ReqAddr(), h, ttl);
|
||||
uint32 tmp_addr = dr->ReqAddr();
|
||||
HashKey k(&tmp_addr, 1);
|
||||
prev_dm = addr_mappings.Insert(&k, new_dm);
|
||||
AddrMap::iterator it = addr_mappings.find(dr->ReqAddr());
|
||||
prev_dm = (it == addr_mappings.end()) ? 0 : it->second;
|
||||
addr_mappings[dr->ReqAddr()] = new_dm;
|
||||
|
||||
if ( new_dm->Failed() && prev_dm && prev_dm->Valid() )
|
||||
{
|
||||
uint32 tmp_addr = dr->ReqAddr();
|
||||
HashKey k2(&tmp_addr, 1);
|
||||
(void) addr_mappings.Insert(&k2, prev_dm);
|
||||
addr_mappings[dr->ReqAddr()] = prev_dm;
|
||||
++keep_prev;
|
||||
}
|
||||
}
|
||||
|
@ -774,17 +820,13 @@ ListVal* DNS_Mgr::AddrListDelta(ListVal* al1, ListVal* al2)
|
|||
|
||||
for ( int i = 0; i < al1->Length(); ++i )
|
||||
{
|
||||
addr_type al1_i = al1->Index(i)->AsAddr();
|
||||
const IPAddr& al1_i = al1->Index(i)->AsAddr();
|
||||
|
||||
int j;
|
||||
for ( j = 0; j < al2->Length(); ++j )
|
||||
{
|
||||
addr_type al2_j = al2->Index(j)->AsAddr();
|
||||
#ifdef BROv6
|
||||
if ( addr_eq(al1_i, al2_j) )
|
||||
#else
|
||||
const IPAddr& al2_j = al2->Index(j)->AsAddr();
|
||||
if ( al1_i == al2_j )
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -800,8 +842,8 @@ void DNS_Mgr::DumpAddrList(FILE* f, ListVal* al)
|
|||
{
|
||||
for ( int i = 0; i < al->Length(); ++i )
|
||||
{
|
||||
addr_type al_i = al->Index(i)->AsAddr();
|
||||
fprintf(f, "%s%s", i > 0 ? "," : "", dotted_addr(al_i));
|
||||
const IPAddr& al_i = al->Index(i)->AsAddr();
|
||||
fprintf(f, "%s%s", i > 0 ? "," : "", al_i.AsString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -814,12 +856,20 @@ void DNS_Mgr::LoadCache(FILE* f)
|
|||
for ( ; ! m->NoMapping() && ! m->InitFailed(); m = new DNS_Mapping(f) )
|
||||
{
|
||||
if ( m->ReqHost() )
|
||||
host_mappings.Insert(m->ReqHost(), m);
|
||||
{
|
||||
if ( host_mappings.find(m->ReqHost()) == host_mappings.end() )
|
||||
{
|
||||
host_mappings[m->ReqHost()].first = 0;
|
||||
host_mappings[m->ReqHost()].second = 0;
|
||||
}
|
||||
if ( m->Type() == AF_INET )
|
||||
host_mappings[m->ReqHost()].first = m;
|
||||
else
|
||||
host_mappings[m->ReqHost()].second = m;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 tmp_addr = m->ReqAddr();
|
||||
HashKey h(&tmp_addr, 1);
|
||||
addr_mappings.Insert(&h, m);
|
||||
addr_mappings[m->ReqAddr()] = m;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -830,26 +880,41 @@ void DNS_Mgr::LoadCache(FILE* f)
|
|||
fclose(f);
|
||||
}
|
||||
|
||||
void DNS_Mgr::Save(FILE* f, PDict(DNS_Mapping)& m)
|
||||
void DNS_Mgr::Save(FILE* f, const AddrMap& m)
|
||||
{
|
||||
IterCookie* cookie = m.InitForIteration();
|
||||
DNS_Mapping* dm;
|
||||
|
||||
while ( (dm = m.NextEntry(cookie)) )
|
||||
dm->Save(f);
|
||||
for ( AddrMap::const_iterator it = m.begin(); it != m.end(); ++it )
|
||||
{
|
||||
if ( it->second )
|
||||
it->second->Save(f);
|
||||
}
|
||||
}
|
||||
|
||||
const char* DNS_Mgr::LookupAddrInCache(dns_mgr_addr_type addr)
|
||||
void DNS_Mgr::Save(FILE* f, const HostMap& m)
|
||||
{
|
||||
HashKey h(&addr, 1);
|
||||
DNS_Mapping* d = dns_mgr->addr_mappings.Lookup(&h);
|
||||
HostMap::const_iterator it;
|
||||
|
||||
if ( ! d )
|
||||
for ( it = m.begin(); it != m.end(); ++it )
|
||||
{
|
||||
if ( it->second.first )
|
||||
it->second.first->Save(f);
|
||||
|
||||
if ( it->second.second )
|
||||
it->second.second->Save(f);
|
||||
}
|
||||
}
|
||||
|
||||
const char* DNS_Mgr::LookupAddrInCache(const IPAddr& addr)
|
||||
{
|
||||
AddrMap::iterator it = dns_mgr->addr_mappings.find(addr);
|
||||
|
||||
if ( it == addr_mappings.end() )
|
||||
return 0;
|
||||
|
||||
DNS_Mapping* d = it->second;
|
||||
|
||||
if ( d->Expired() )
|
||||
{
|
||||
dns_mgr->addr_mappings.Remove(&h);
|
||||
dns_mgr->addr_mappings.erase(it);
|
||||
delete d;
|
||||
return 0;
|
||||
}
|
||||
|
@ -861,23 +926,32 @@ const char* DNS_Mgr::LookupAddrInCache(dns_mgr_addr_type addr)
|
|||
|
||||
TableVal* DNS_Mgr::LookupNameInCache(string name)
|
||||
{
|
||||
DNS_Mapping* d = dns_mgr->host_mappings.Lookup(name.c_str());
|
||||
|
||||
if ( ! d || ! d->names )
|
||||
HostMap::iterator it = dns_mgr->host_mappings.find(name);
|
||||
if ( it == dns_mgr->host_mappings.end() )
|
||||
return 0;
|
||||
|
||||
if ( d->Expired() )
|
||||
DNS_Mapping* d4 = it->second.first;
|
||||
DNS_Mapping* d6 = it->second.second;
|
||||
|
||||
if ( ! d4 || ! d4->names || ! d6 || ! d6->names )
|
||||
return 0;
|
||||
|
||||
if ( d4->Expired() || d6->Expired() )
|
||||
{
|
||||
HashKey h(name.c_str());
|
||||
dns_mgr->host_mappings.Remove(&h);
|
||||
delete d;
|
||||
dns_mgr->host_mappings.erase(it);
|
||||
delete d4;
|
||||
delete d6;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return d->AddrsSet();
|
||||
TableVal* tv4 = d4->AddrsSet();
|
||||
TableVal* tv6 = d6->AddrsSet();
|
||||
tv4->AddTo(tv6, false);
|
||||
Unref(tv4);
|
||||
return tv6;
|
||||
}
|
||||
|
||||
void DNS_Mgr::AsyncLookupAddr(dns_mgr_addr_type host, LookupCallback* callback)
|
||||
void DNS_Mgr::AsyncLookupAddr(const IPAddr& host, LookupCallback* callback)
|
||||
{
|
||||
if ( ! did_init )
|
||||
Init();
|
||||
|
@ -956,10 +1030,15 @@ void DNS_Mgr::IssueAsyncRequests()
|
|||
++num_requests;
|
||||
|
||||
DNS_Mgr_Request* dr;
|
||||
DNS_Mgr_Request* dr6 = 0;
|
||||
|
||||
if ( req->IsAddrReq() )
|
||||
dr = new DNS_Mgr_Request(req->host);
|
||||
else
|
||||
dr = new DNS_Mgr_Request(req->name.c_str());
|
||||
{
|
||||
dr = new DNS_Mgr_Request(req->name.c_str(), AF_INET);
|
||||
dr6 = new DNS_Mgr_Request(req->name.c_str(), AF_INET6);
|
||||
}
|
||||
|
||||
if ( ! dr->MakeRequest(nb_dns) )
|
||||
{
|
||||
|
@ -969,6 +1048,14 @@ void DNS_Mgr::IssueAsyncRequests()
|
|||
continue;
|
||||
}
|
||||
|
||||
if ( dr6 && ! dr6->MakeRequest(nb_dns) )
|
||||
{
|
||||
reporter->Warning("can't issue DNS request");
|
||||
++failed;
|
||||
req->Timeout();
|
||||
continue;
|
||||
}
|
||||
|
||||
req->time = current_time();
|
||||
asyncs_timeouts.push(req);
|
||||
|
||||
|
@ -987,7 +1074,7 @@ double DNS_Mgr::NextTimestamp(double* network_time)
|
|||
return asyncs_timeouts.size() ? timer_mgr->Time() : -1.0;
|
||||
}
|
||||
|
||||
void DNS_Mgr::CheckAsyncAddrRequest(dns_mgr_addr_type addr, bool timeout)
|
||||
void DNS_Mgr::CheckAsyncAddrRequest(const IPAddr& addr, bool timeout)
|
||||
{
|
||||
// Note that this code is a mirror of that for CheckAsyncHostRequest.
|
||||
|
||||
|
@ -1060,11 +1147,18 @@ void DNS_Mgr::Flush()
|
|||
{
|
||||
DoProcess(false);
|
||||
|
||||
IterCookie* cookie = addr_mappings.InitForIteration();
|
||||
DNS_Mapping* dm;
|
||||
HostMap::iterator it;
|
||||
for ( it = host_mappings.begin(); it != host_mappings.end(); ++it )
|
||||
{
|
||||
delete it->second.first;
|
||||
delete it->second.second;
|
||||
}
|
||||
|
||||
host_mappings.Clear();
|
||||
addr_mappings.Clear();
|
||||
for ( AddrMap::iterator it2 = addr_mappings.begin(); it2 != addr_mappings.end(); ++it2 )
|
||||
delete it2->second;
|
||||
|
||||
host_mappings.clear();
|
||||
addr_mappings.clear();
|
||||
}
|
||||
|
||||
void DNS_Mgr::Process()
|
||||
|
@ -1107,6 +1201,14 @@ void DNS_Mgr::DoProcess(bool flush)
|
|||
else if ( status > 0 )
|
||||
{
|
||||
DNS_Mgr_Request* dr = (DNS_Mgr_Request*) r.cookie;
|
||||
|
||||
bool do_host_timeout = true;
|
||||
if ( dr->ReqHost() &&
|
||||
host_mappings.find(dr->ReqHost()) == host_mappings.end() )
|
||||
// Don't timeout when this is the first result in an expected pair
|
||||
// (one result each for A and AAAA queries).
|
||||
do_host_timeout = false;
|
||||
|
||||
if ( dr->RequestPending() )
|
||||
{
|
||||
AddResult(dr, &r);
|
||||
|
@ -1116,7 +1218,7 @@ void DNS_Mgr::DoProcess(bool flush)
|
|||
if ( ! dr->ReqHost() )
|
||||
CheckAsyncAddrRequest(dr->ReqAddr(), true);
|
||||
else
|
||||
CheckAsyncHostRequest(dr->ReqHost(), true);
|
||||
CheckAsyncHostRequest(dr->ReqHost(), do_host_timeout);
|
||||
|
||||
IssueAsyncRequests();
|
||||
|
||||
|
@ -1167,7 +1269,7 @@ void DNS_Mgr::GetStats(Stats* stats)
|
|||
stats->successful = successful;
|
||||
stats->failed = failed;
|
||||
stats->pending = asyncs_pending;
|
||||
stats->cached_hosts = host_mappings.Length();
|
||||
stats->cached_addresses = addr_mappings.Length();
|
||||
stats->cached_hosts = host_mappings.size();
|
||||
stats->cached_addresses = addr_mappings.size();
|
||||
}
|
||||
|
||||
|
|
|
@ -6,12 +6,14 @@
|
|||
#include <list>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
|
||||
#include "util.h"
|
||||
#include "BroList.h"
|
||||
#include "Dict.h"
|
||||
#include "EventHandler.h"
|
||||
#include "IOSource.h"
|
||||
#include "IPAddr.h"
|
||||
|
||||
class Val;
|
||||
class ListVal;
|
||||
|
@ -27,7 +29,6 @@ struct nb_dns_result;
|
|||
declare(PDict,ListVal);
|
||||
|
||||
class DNS_Mapping;
|
||||
declare(PDict,DNS_Mapping);
|
||||
|
||||
enum DNS_MgrMode {
|
||||
DNS_PRIME, // used to prime the cache
|
||||
|
@ -39,10 +40,6 @@ enum DNS_MgrMode {
|
|||
// Number of seconds we'll wait for a reply.
|
||||
#define DNS_TIMEOUT 5
|
||||
|
||||
// ### For now, we don't support IPv6 lookups. When we do, this
|
||||
// should become addr_type.
|
||||
typedef uint32 dns_mgr_addr_type;
|
||||
|
||||
class DNS_Mgr : public IOSource {
|
||||
public:
|
||||
DNS_Mgr(DNS_MgrMode mode);
|
||||
|
@ -55,7 +52,7 @@ public:
|
|||
// a set of addr.
|
||||
TableVal* LookupHost(const char* host);
|
||||
|
||||
Val* LookupAddr(uint32 addr);
|
||||
Val* LookupAddr(const IPAddr& addr);
|
||||
|
||||
// Define the directory where to store the data.
|
||||
void SetDir(const char* arg_dir) { dir = copy_string(arg_dir); }
|
||||
|
@ -64,7 +61,7 @@ public:
|
|||
void Resolve();
|
||||
int Save();
|
||||
|
||||
const char* LookupAddrInCache(dns_mgr_addr_type addr);
|
||||
const char* LookupAddrInCache(const IPAddr& addr);
|
||||
TableVal* LookupNameInCache(string name);
|
||||
|
||||
// Support for async lookups.
|
||||
|
@ -78,7 +75,7 @@ public:
|
|||
virtual void Timeout() = 0;
|
||||
};
|
||||
|
||||
void AsyncLookupAddr(dns_mgr_addr_type host, LookupCallback* callback);
|
||||
void AsyncLookupAddr(const IPAddr& host, LookupCallback* callback);
|
||||
void AsyncLookupName(string name, LookupCallback* callback);
|
||||
|
||||
struct Stats {
|
||||
|
@ -107,8 +104,11 @@ protected:
|
|||
ListVal* AddrListDelta(ListVal* al1, ListVal* al2);
|
||||
void DumpAddrList(FILE* f, ListVal* al);
|
||||
|
||||
typedef map<string, pair<DNS_Mapping*, DNS_Mapping*> > HostMap;
|
||||
typedef map<IPAddr, DNS_Mapping*> AddrMap;
|
||||
void LoadCache(FILE* f);
|
||||
void Save(FILE* f, PDict(DNS_Mapping)& m);
|
||||
void Save(FILE* f, const AddrMap& m);
|
||||
void Save(FILE* f, const HostMap& m);
|
||||
|
||||
// Selects on the fd to see if there is an answer available (timeout
|
||||
// is secs). Returns 0 on timeout, -1 on EINTR or other error, and 1
|
||||
|
@ -120,7 +120,7 @@ protected:
|
|||
|
||||
// Finish the request if we have a result. If not, time it out if
|
||||
// requested.
|
||||
void CheckAsyncAddrRequest(dns_mgr_addr_type addr, bool timeout);
|
||||
void CheckAsyncAddrRequest(const IPAddr& addr, bool timeout);
|
||||
void CheckAsyncHostRequest(const char* host, bool timeout);
|
||||
|
||||
// Process outstanding requests.
|
||||
|
@ -136,8 +136,8 @@ protected:
|
|||
|
||||
PDict(ListVal) services;
|
||||
|
||||
PDict(DNS_Mapping) host_mappings;
|
||||
PDict(DNS_Mapping) addr_mappings;
|
||||
HostMap host_mappings;
|
||||
AddrMap addr_mappings;
|
||||
|
||||
DNS_mgr_request_list requests;
|
||||
|
||||
|
@ -163,7 +163,7 @@ protected:
|
|||
|
||||
struct AsyncRequest {
|
||||
double time;
|
||||
dns_mgr_addr_type host;
|
||||
IPAddr host;
|
||||
string name;
|
||||
CallbackList callbacks;
|
||||
|
||||
|
@ -204,7 +204,7 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
typedef map<dns_mgr_addr_type, AsyncRequest*> AsyncRequestAddrMap;
|
||||
typedef map<IPAddr, AsyncRequest*> AsyncRequestAddrMap;
|
||||
AsyncRequestAddrMap asyncs_addrs;
|
||||
|
||||
typedef map<string, AsyncRequest*> AsyncRequestNameMap;
|
||||
|
|
127
src/DPM.cc
127
src/DPM.cc
|
@ -11,53 +11,28 @@
|
|||
#include "ConnSizeAnalyzer.h"
|
||||
|
||||
|
||||
ExpectedConn::ExpectedConn(const uint32* _orig, const uint32* _resp,
|
||||
ExpectedConn::ExpectedConn(const IPAddr& _orig, const IPAddr& _resp,
|
||||
uint16 _resp_p, uint16 _proto)
|
||||
{
|
||||
if ( orig )
|
||||
copy_addr(_orig, orig);
|
||||
if ( _orig == IPAddr(string("0.0.0.0")) )
|
||||
// don't use the IPv4 mapping, use the literal unspecified address
|
||||
// to indicate a wildcard
|
||||
orig = IPAddr(string("::"));
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < NUM_ADDR_WORDS; ++i )
|
||||
orig[i] = 0;
|
||||
}
|
||||
|
||||
copy_addr(_resp, resp);
|
||||
|
||||
resp_p = _resp_p;
|
||||
proto = _proto;
|
||||
}
|
||||
|
||||
ExpectedConn::ExpectedConn(uint32 _orig, uint32 _resp,
|
||||
uint16 _resp_p, uint16 _proto)
|
||||
{
|
||||
#ifdef BROv6
|
||||
// Use the IPv4-within-IPv6 convention, as this is what's
|
||||
// needed when we mix uint32's (like in this construction)
|
||||
// with addr_type's (for example, when looking up expected
|
||||
// connections).
|
||||
|
||||
orig[0] = orig[1] = orig[2] = 0;
|
||||
resp[0] = resp[1] = resp[2] = 0;
|
||||
orig[3] = _orig;
|
||||
resp[3] = _resp;
|
||||
#else
|
||||
orig[0] = _orig;
|
||||
resp[0] = _resp;
|
||||
#endif
|
||||
orig = _orig;
|
||||
resp = _resp;
|
||||
resp_p = _resp_p;
|
||||
proto = _proto;
|
||||
}
|
||||
|
||||
ExpectedConn::ExpectedConn(const ExpectedConn& c)
|
||||
{
|
||||
copy_addr(c.orig, orig);
|
||||
copy_addr(c.resp, resp);
|
||||
orig = c.orig;
|
||||
resp = c.resp;
|
||||
resp_p = c.resp_p;
|
||||
proto = c.proto;
|
||||
}
|
||||
|
||||
|
||||
DPM::DPM()
|
||||
: expected_conns_queue(AssignedAnalyzer::compare)
|
||||
{
|
||||
|
@ -99,7 +74,7 @@ void DPM::PostScriptInit()
|
|||
|
||||
void DPM::AddConfig(const Analyzer::Config& cfg)
|
||||
{
|
||||
#ifdef USE_PERFTOOLS
|
||||
#ifdef USE_PERFTOOLS_DEBUG
|
||||
HeapLeakChecker::Disabler disabler;
|
||||
#endif
|
||||
|
||||
|
@ -158,23 +133,18 @@ AnalyzerTag::Tag DPM::GetExpected(int proto, const Connection* conn)
|
|||
ExpectedConn c(conn->OrigAddr(), conn->RespAddr(),
|
||||
ntohs(conn->RespPort()), proto);
|
||||
|
||||
// Can't use sizeof(c) due to potential alignment issues.
|
||||
// FIXME: I guess this is still not portable ...
|
||||
HashKey key(&c, sizeof(c.orig) + sizeof(c.resp) +
|
||||
sizeof(c.resp_p) + sizeof(c.proto));
|
||||
|
||||
AssignedAnalyzer* a = expected_conns.Lookup(&key);
|
||||
HashKey* key = BuildExpectedConnHashKey(c);
|
||||
AssignedAnalyzer* a = expected_conns.Lookup(key);
|
||||
delete key;
|
||||
|
||||
if ( ! a )
|
||||
{
|
||||
// Wildcard for originator.
|
||||
for ( int i = 0; i < NUM_ADDR_WORDS; ++i )
|
||||
c.orig[i] = 0;
|
||||
c.orig = IPAddr(string("::"));
|
||||
|
||||
HashKey key(&c, sizeof(c.orig) + sizeof(c.resp) +
|
||||
sizeof(c.resp_p) + sizeof(c.proto));
|
||||
|
||||
a = expected_conns.Lookup(&key);
|
||||
HashKey* key = BuildExpectedConnHashKey(c);
|
||||
a = expected_conns.Lookup(key);
|
||||
delete key;
|
||||
}
|
||||
|
||||
if ( ! a )
|
||||
|
@ -215,46 +185,8 @@ bool DPM::BuildInitialAnalyzerTree(TransportProto proto, Connection* conn,
|
|||
break;
|
||||
|
||||
case TRANSPORT_ICMP: {
|
||||
const struct icmp* icmpp = (const struct icmp *) data;
|
||||
switch ( icmpp->icmp_type ) {
|
||||
|
||||
case ICMP_ECHO:
|
||||
case ICMP_ECHOREPLY:
|
||||
if ( ICMP_Echo_Analyzer::Available() )
|
||||
{
|
||||
root = icmp = new ICMP_Echo_Analyzer(conn);
|
||||
DBG_DPD(conn, "activated ICMP Echo analyzer");
|
||||
}
|
||||
break;
|
||||
|
||||
case ICMP_REDIRECT:
|
||||
if ( ICMP_Redir_Analyzer::Available() )
|
||||
{
|
||||
root = new ICMP_Redir_Analyzer(conn);
|
||||
DBG_DPD(conn, "activated ICMP Redir analyzer");
|
||||
}
|
||||
break;
|
||||
|
||||
case ICMP_UNREACH:
|
||||
if ( ICMP_Unreachable_Analyzer::Available() )
|
||||
{
|
||||
root = icmp = new ICMP_Unreachable_Analyzer(conn);
|
||||
DBG_DPD(conn, "activated ICMP Unreachable analyzer");
|
||||
}
|
||||
break;
|
||||
|
||||
case ICMP_TIMXCEED:
|
||||
if ( ICMP_TimeExceeded_Analyzer::Available() )
|
||||
{
|
||||
root = icmp = new ICMP_TimeExceeded_Analyzer(conn);
|
||||
DBG_DPD(conn, "activated ICMP Time Exceeded analyzer");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! root )
|
||||
root = icmp = new ICMP_Analyzer(conn);
|
||||
|
||||
DBG_DPD(conn, "activated ICMP analyzer");
|
||||
analyzed = true;
|
||||
break;
|
||||
}
|
||||
|
@ -404,7 +336,8 @@ bool DPM::BuildInitialAnalyzerTree(TransportProto proto, Connection* conn,
|
|||
return true;
|
||||
}
|
||||
|
||||
void DPM::ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p,
|
||||
void DPM::ExpectConnection(const IPAddr& orig, const IPAddr& resp,
|
||||
uint16 resp_p,
|
||||
TransportProto proto, AnalyzerTag::Tag analyzer,
|
||||
double timeout, void* cookie)
|
||||
{
|
||||
|
@ -416,11 +349,7 @@ void DPM::ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p,
|
|||
{
|
||||
if ( ! a->deleted )
|
||||
{
|
||||
HashKey* key = new HashKey(&a->conn,
|
||||
sizeof(a->conn.orig) +
|
||||
sizeof(a->conn.resp) +
|
||||
sizeof(a->conn.resp_p) +
|
||||
sizeof(a->conn.proto));
|
||||
HashKey* key = BuildExpectedConnHashKey(a->conn);
|
||||
expected_conns.Remove(key);
|
||||
delete key;
|
||||
}
|
||||
|
@ -439,10 +368,9 @@ void DPM::ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p,
|
|||
|
||||
ExpectedConn c(orig, resp, resp_p, proto);
|
||||
|
||||
HashKey key(&c, sizeof(c.orig) + sizeof(c.resp) +
|
||||
sizeof(c.resp_p) + sizeof(c.proto));
|
||||
HashKey* key = BuildExpectedConnHashKey(c);
|
||||
|
||||
AssignedAnalyzer* a = expected_conns.Lookup(&key);
|
||||
AssignedAnalyzer* a = expected_conns.Lookup(key);
|
||||
|
||||
if ( a )
|
||||
a->deleted = true;
|
||||
|
@ -454,8 +382,9 @@ void DPM::ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p,
|
|||
a->timeout = network_time + timeout;
|
||||
a->deleted = false;
|
||||
|
||||
expected_conns.Insert(&key, a);
|
||||
expected_conns.Insert(key, a);
|
||||
expected_conns_queue.push(a);
|
||||
delete key;
|
||||
}
|
||||
|
||||
void DPM::Done()
|
||||
|
@ -466,11 +395,7 @@ void DPM::Done()
|
|||
AssignedAnalyzer* a = expected_conns_queue.top();
|
||||
if ( ! a->deleted )
|
||||
{
|
||||
HashKey* key = new HashKey(&a->conn,
|
||||
sizeof(a->conn.orig) +
|
||||
sizeof(a->conn.resp) +
|
||||
sizeof(a->conn.resp_p) +
|
||||
sizeof(a->conn.proto));
|
||||
HashKey* key = BuildExpectedConnHashKey(a->conn);
|
||||
expected_conns.Remove(key);
|
||||
delete key;
|
||||
}
|
||||
|
|
14
src/DPM.h
14
src/DPM.h
|
@ -27,19 +27,13 @@
|
|||
// Map to assign expected connections to analyzers.
|
||||
class ExpectedConn {
|
||||
public:
|
||||
// This form can be used for IPv6 as well as IPv4.
|
||||
ExpectedConn(const uint32* _orig, const uint32* _resp,
|
||||
ExpectedConn(const IPAddr& _orig, const IPAddr& _resp,
|
||||
uint16 _resp_p, uint16 _proto);
|
||||
|
||||
// This form only works for expecting an IPv4 connection. Note
|
||||
// that we do the right thing whether we're built IPv4-only or
|
||||
// BROv6.
|
||||
ExpectedConn(uint32 _orig, uint32 _resp, uint16 _resp_p, uint16 _proto);
|
||||
|
||||
ExpectedConn(const ExpectedConn& c);
|
||||
|
||||
uint32 orig[NUM_ADDR_WORDS];
|
||||
uint32 resp[NUM_ADDR_WORDS];
|
||||
IPAddr orig;
|
||||
IPAddr resp;
|
||||
uint16 resp_p;
|
||||
uint16 proto;
|
||||
};
|
||||
|
@ -90,7 +84,7 @@ public:
|
|||
// Schedules a particular analyzer for an upcoming connection.
|
||||
// 0 acts as a wildcard for orig. (Cookie is currently unused.
|
||||
// Eventually, we may pass it on to the analyzer).
|
||||
void ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p,
|
||||
void ExpectConnection(const IPAddr& orig, const IPAddr& resp, uint16 resp_p,
|
||||
TransportProto proto, AnalyzerTag::Tag analyzer,
|
||||
double timeout, void* cookie);
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ int TraceState::LogTrace(const char* fmt, ...)
|
|||
|
||||
if ( ! loc.filename )
|
||||
{
|
||||
loc.filename = "<no filename>";
|
||||
loc.filename = copy_string("<no filename>");
|
||||
loc.last_line = 0;
|
||||
}
|
||||
|
||||
|
@ -735,7 +735,7 @@ string get_context_description(const Stmt* stmt, const Frame* frame)
|
|||
loc = *stmt->GetLocationInfo();
|
||||
else
|
||||
{
|
||||
loc.filename = "<no filename>";
|
||||
loc.filename = copy_string("<no filename>");
|
||||
loc.last_line = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ DebugLogger::Stream DebugLogger::streams[NUM_DBGS] = {
|
|||
{ "compressor", 0, false }, {"string", 0, false },
|
||||
{ "notifiers", 0, false }, { "main-loop", 0, false },
|
||||
{ "dpd", 0, false }, { "tm", 0, false },
|
||||
{ "logging", 0, false }
|
||||
{ "logging", 0, false }, { "threading", 0, false }
|
||||
};
|
||||
|
||||
DebugLogger::DebugLogger(const char* filename)
|
||||
|
|
|
@ -24,6 +24,7 @@ enum DebugStream {
|
|||
DBG_DPD, // Dynamic application detection framework
|
||||
DBG_TM, // Time-machine packet input via Brocolli
|
||||
DBG_LOGGING, // Logging streams
|
||||
DBG_THREADING, // Threading system
|
||||
|
||||
NUM_DBGS // Has to be last
|
||||
};
|
||||
|
|
10
src/Desc.cc
10
src/Desc.cc
|
@ -157,6 +157,16 @@ void ODesc::Add(double d)
|
|||
}
|
||||
}
|
||||
|
||||
void ODesc::Add(const IPAddr& addr)
|
||||
{
|
||||
Add(addr.AsString());
|
||||
}
|
||||
|
||||
void ODesc::Add(const IPPrefix& prefix)
|
||||
{
|
||||
Add(prefix.AsString());
|
||||
}
|
||||
|
||||
void ODesc::AddCS(const char* s)
|
||||
{
|
||||
int n = strlen(s);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <stdio.h>
|
||||
#include <list>
|
||||
#include <utility>
|
||||
|
||||
#include "BroString.h"
|
||||
|
||||
typedef enum {
|
||||
|
@ -21,6 +22,8 @@ typedef enum {
|
|||
} desc_style;
|
||||
|
||||
class BroFile;
|
||||
class IPAddr;
|
||||
class IPPrefix;
|
||||
|
||||
class ODesc {
|
||||
public:
|
||||
|
@ -68,11 +71,14 @@ public:
|
|||
|
||||
void Add(const char* s, int do_indent=1);
|
||||
void AddN(const char* s, int len) { AddBytes(s, len); }
|
||||
void Add(const string& s) { AddBytes(s.data(), s.size()); }
|
||||
void Add(int i);
|
||||
void Add(uint32 u);
|
||||
void Add(int64 i);
|
||||
void Add(uint64 u);
|
||||
void Add(double d);
|
||||
void Add(const IPAddr& addr);
|
||||
void Add(const IPPrefix& prefix);
|
||||
|
||||
// Add s as a counted string.
|
||||
void AddCS(const char* s);
|
||||
|
|
|
@ -10,11 +10,6 @@
|
|||
|
||||
Discarder::Discarder()
|
||||
{
|
||||
ip_hdr = internal_type("ip_hdr")->AsRecordType();
|
||||
tcp_hdr = internal_type("tcp_hdr")->AsRecordType();
|
||||
udp_hdr = internal_type("udp_hdr")->AsRecordType();
|
||||
icmp_hdr = internal_type("icmp_hdr")->AsRecordType();
|
||||
|
||||
check_ip = internal_func("discarder_check_ip");
|
||||
check_tcp = internal_func("discarder_check_tcp");
|
||||
check_udp = internal_func("discarder_check_udp");
|
||||
|
@ -36,12 +31,10 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen)
|
|||
{
|
||||
int discard_packet = 0;
|
||||
|
||||
const struct ip* ip4 = ip->IP4_Hdr();
|
||||
|
||||
if ( check_ip )
|
||||
{
|
||||
val_list* args = new val_list;
|
||||
args->append(BuildHeader(ip4));
|
||||
args->append(ip->BuildPktHdrVal());
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -59,19 +52,18 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen)
|
|||
return discard_packet;
|
||||
}
|
||||
|
||||
int proto = ip4->ip_p;
|
||||
int proto = ip->NextProto();
|
||||
if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP &&
|
||||
proto != IPPROTO_ICMP )
|
||||
// This is not a protocol we understand.
|
||||
return 0;
|
||||
|
||||
// XXX shall we only check the first packet???
|
||||
uint32 frag_field = ntohs(ip4->ip_off);
|
||||
if ( (frag_field & 0x3fff) != 0 )
|
||||
if ( ip->IsFragment() )
|
||||
// Never check any fragment.
|
||||
return 0;
|
||||
|
||||
int ip_hdr_len = ip4->ip_hl * 4;
|
||||
int ip_hdr_len = ip->HdrLen();
|
||||
len -= ip_hdr_len; // remove IP header
|
||||
caplen -= ip_hdr_len;
|
||||
|
||||
|
@ -87,7 +79,7 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen)
|
|||
|
||||
// Where the data starts - if this is a protocol we know about,
|
||||
// this gets advanced past the transport header.
|
||||
const u_char* data = ((u_char*) ip4 + ip_hdr_len);
|
||||
const u_char* data = ip->Payload();
|
||||
|
||||
if ( is_tcp )
|
||||
{
|
||||
|
@ -97,8 +89,7 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen)
|
|||
int th_len = tp->th_off * 4;
|
||||
|
||||
val_list* args = new val_list;
|
||||
args->append(BuildHeader(ip4));
|
||||
args->append(BuildHeader(tp, len));
|
||||
args->append(ip->BuildPktHdrVal());
|
||||
args->append(BuildData(data, th_len, len, caplen));
|
||||
|
||||
try
|
||||
|
@ -123,8 +114,7 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen)
|
|||
int uh_len = sizeof (struct udphdr);
|
||||
|
||||
val_list* args = new val_list;
|
||||
args->append(BuildHeader(ip4));
|
||||
args->append(BuildHeader(up));
|
||||
args->append(ip->BuildPktHdrVal());
|
||||
args->append(BuildData(data, uh_len, len, caplen));
|
||||
|
||||
try
|
||||
|
@ -148,8 +138,7 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen)
|
|||
const struct icmp* ih = (const struct icmp*) data;
|
||||
|
||||
val_list* args = new val_list;
|
||||
args->append(BuildHeader(ip4));
|
||||
args->append(BuildHeader(ih));
|
||||
args->append(ip->BuildPktHdrVal());
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -168,62 +157,6 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen)
|
|||
return discard_packet;
|
||||
}
|
||||
|
||||
Val* Discarder::BuildHeader(const struct ip* ip)
|
||||
{
|
||||
RecordVal* hdr = new RecordVal(ip_hdr);
|
||||
|
||||
hdr->Assign(0, new Val(ip->ip_hl * 4, TYPE_COUNT));
|
||||
hdr->Assign(1, new Val(ip->ip_tos, TYPE_COUNT));
|
||||
hdr->Assign(2, new Val(ntohs(ip->ip_len), TYPE_COUNT));
|
||||
hdr->Assign(3, new Val(ntohs(ip->ip_id), TYPE_COUNT));
|
||||
hdr->Assign(4, new Val(ip->ip_ttl, TYPE_COUNT));
|
||||
hdr->Assign(5, new Val(ip->ip_p, TYPE_COUNT));
|
||||
hdr->Assign(6, new AddrVal(ip->ip_src.s_addr));
|
||||
hdr->Assign(7, new AddrVal(ip->ip_dst.s_addr));
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
Val* Discarder::BuildHeader(const struct tcphdr* tp, int tcp_len)
|
||||
{
|
||||
RecordVal* hdr = new RecordVal(tcp_hdr);
|
||||
|
||||
hdr->Assign(0, new PortVal(ntohs(tp->th_sport), TRANSPORT_TCP));
|
||||
hdr->Assign(1, new PortVal(ntohs(tp->th_dport), TRANSPORT_TCP));
|
||||
hdr->Assign(2, new Val(uint32(ntohl(tp->th_seq)), TYPE_COUNT));
|
||||
hdr->Assign(3, new Val(uint32(ntohl(tp->th_ack)), TYPE_COUNT));
|
||||
|
||||
int tcp_hdr_len = tp->th_off * 4;
|
||||
|
||||
hdr->Assign(4, new Val(tcp_hdr_len, TYPE_COUNT));
|
||||
hdr->Assign(5, new Val(tcp_len - tcp_hdr_len, TYPE_COUNT));
|
||||
|
||||
hdr->Assign(6, new Val(tp->th_flags, TYPE_COUNT));
|
||||
hdr->Assign(7, new Val(ntohs(tp->th_win), TYPE_COUNT));
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
Val* Discarder::BuildHeader(const struct udphdr* up)
|
||||
{
|
||||
RecordVal* hdr = new RecordVal(udp_hdr);
|
||||
|
||||
hdr->Assign(0, new PortVal(ntohs(up->uh_sport), TRANSPORT_UDP));
|
||||
hdr->Assign(1, new PortVal(ntohs(up->uh_dport), TRANSPORT_UDP));
|
||||
hdr->Assign(2, new Val(ntohs(up->uh_ulen), TYPE_COUNT));
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
Val* Discarder::BuildHeader(const struct icmp* icmp)
|
||||
{
|
||||
RecordVal* hdr = new RecordVal(icmp_hdr);
|
||||
|
||||
hdr->Assign(0, new Val(icmp->icmp_type, TYPE_COUNT));
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
Val* Discarder::BuildData(const u_char* data, int hdrlen, int len, int caplen)
|
||||
{
|
||||
len -= hdrlen;
|
||||
|
|
|
@ -25,17 +25,8 @@ public:
|
|||
int NextPacket(const IP_Hdr* ip, int len, int caplen);
|
||||
|
||||
protected:
|
||||
Val* BuildHeader(const struct ip* ip);
|
||||
Val* BuildHeader(const struct tcphdr* tp, int tcp_len);
|
||||
Val* BuildHeader(const struct udphdr* up);
|
||||
Val* BuildHeader(const struct icmp* icmp);
|
||||
Val* BuildData(const u_char* data, int hdrlen, int len, int caplen);
|
||||
|
||||
RecordType* ip_hdr;
|
||||
RecordType* tcp_hdr;
|
||||
RecordType* udp_hdr;
|
||||
RecordType* icmp_hdr;
|
||||
|
||||
Func* check_ip;
|
||||
Func* check_tcp;
|
||||
Func* check_udp;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
#include "List.h"
|
||||
#include "BroList.h"
|
||||
#include "net_util.h"
|
||||
|
||||
class Func;
|
||||
class FuncType;
|
||||
|
|
210
src/Expr.cc
210
src/Expr.cc
|
@ -14,6 +14,7 @@
|
|||
#include "Net.h"
|
||||
#include "Traverse.h"
|
||||
#include "Trigger.h"
|
||||
#include "IPAddr.h"
|
||||
|
||||
const char* expr_name(BroExprTag t)
|
||||
{
|
||||
|
@ -834,30 +835,30 @@ Val* BinaryExpr::StringFold(Val* v1, Val* v2) const
|
|||
|
||||
Val* BinaryExpr::AddrFold(Val* v1, Val* v2) const
|
||||
{
|
||||
addr_type a1 = v1->AsAddr();
|
||||
addr_type a2 = v2->AsAddr();
|
||||
IPAddr a1 = v1->AsAddr();
|
||||
IPAddr a2 = v2->AsAddr();
|
||||
int result = 0;
|
||||
|
||||
switch ( tag ) {
|
||||
#undef DO_FOLD
|
||||
#ifdef BROv6
|
||||
#define DO_FOLD(sense) { result = memcmp(a1, a2, 16) sense 0; break; }
|
||||
#else
|
||||
#define DO_FOLD(sense) \
|
||||
{ \
|
||||
a1 = ntohl(a1); \
|
||||
a2 = ntohl(a2); \
|
||||
result = (a1 < a2 ? -1 : (a1 == a2 ? 0 : 1)) sense 0; \
|
||||
break; \
|
||||
}
|
||||
#endif
|
||||
|
||||
case EXPR_LT: DO_FOLD(<)
|
||||
case EXPR_LE: DO_FOLD(<=)
|
||||
case EXPR_EQ: DO_FOLD(==)
|
||||
case EXPR_NE: DO_FOLD(!=)
|
||||
case EXPR_GE: DO_FOLD(>=)
|
||||
case EXPR_GT: DO_FOLD(>)
|
||||
case EXPR_LT:
|
||||
result = a1 < a2;
|
||||
break;
|
||||
case EXPR_LE:
|
||||
result = a1 < a2 || a1 == a2;
|
||||
break;
|
||||
case EXPR_EQ:
|
||||
result = a1 == a2;
|
||||
break;
|
||||
case EXPR_NE:
|
||||
result = a1 != a2;
|
||||
break;
|
||||
case EXPR_GE:
|
||||
result = ! ( a1 < a2 );
|
||||
break;
|
||||
case EXPR_GT:
|
||||
result = ( ! ( a1 < a2 ) ) && ( a1 != a2 );
|
||||
break;
|
||||
|
||||
default:
|
||||
BadTag("BinaryExpr::AddrFold", expr_name(tag));
|
||||
|
@ -868,20 +869,13 @@ Val* BinaryExpr::AddrFold(Val* v1, Val* v2) const
|
|||
|
||||
Val* BinaryExpr::SubNetFold(Val* v1, Val* v2) const
|
||||
{
|
||||
subnet_type* n1 = v1->AsSubNet();
|
||||
subnet_type* n2 = v2->AsSubNet();
|
||||
|
||||
if ( n1->width != n2->width )
|
||||
return new Val(0, TYPE_BOOL);
|
||||
|
||||
#ifdef BROv6
|
||||
if ( memcmp(n1->net, n2->net, 16) )
|
||||
#else
|
||||
if ( n1->net != n2->net )
|
||||
#endif
|
||||
return new Val(0, TYPE_BOOL);
|
||||
const IPPrefix& n1 = v1->AsSubNet();
|
||||
const IPPrefix& n2 = v2->AsSubNet();
|
||||
|
||||
if ( n1 == n2 )
|
||||
return new Val(1, TYPE_BOOL);
|
||||
else
|
||||
return new Val(0, TYPE_BOOL);
|
||||
}
|
||||
|
||||
void BinaryExpr::SwapOps()
|
||||
|
@ -1681,15 +1675,13 @@ DivideExpr::DivideExpr(Expr* arg_op1, Expr* arg_op2)
|
|||
|
||||
Val* DivideExpr::AddrFold(Val* v1, Val* v2) const
|
||||
{
|
||||
addr_type a1 = v1->AsAddr();
|
||||
|
||||
uint32 mask;
|
||||
if ( v2->Type()->Tag() == TYPE_COUNT )
|
||||
mask = static_cast<uint32>(v2->InternalUnsigned());
|
||||
else
|
||||
mask = static_cast<uint32>(v2->InternalInt());
|
||||
|
||||
return new SubNetVal(a1, mask);
|
||||
return new SubNetVal(v1->AsAddr(), mask);
|
||||
}
|
||||
|
||||
Expr* DivideExpr::DoSimplify()
|
||||
|
@ -2672,8 +2664,6 @@ void AssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) const
|
|||
Error("bad table insertion");
|
||||
|
||||
TableVal* tv = aggr->AsTableVal();
|
||||
const TableType* tt = tv->Type()->AsTableType();
|
||||
const BroType* yt = tv->Type()->YieldType();
|
||||
|
||||
Val* index = op1->Eval(f);
|
||||
Val* v = op2->Eval(f);
|
||||
|
@ -3643,151 +3633,6 @@ bool FieldAssignExpr::DoUnserialize(UnserialInfo* info)
|
|||
return true;
|
||||
}
|
||||
|
||||
RecordMatchExpr::RecordMatchExpr(Expr* op1 /* record to match */,
|
||||
Expr* op2 /* cases to match against */)
|
||||
: BinaryExpr(EXPR_MATCH, op1, op2)
|
||||
{
|
||||
BroType* result_type = 0;
|
||||
|
||||
// Make sure the second argument is of a suitable type.
|
||||
if ( ! op2->Type()->IsSet() )
|
||||
{
|
||||
ExprError("matching must be done against a set of match records");
|
||||
return;
|
||||
}
|
||||
|
||||
type_list* elt_types = op2->Type()->AsSetType()->Indices()->Types();
|
||||
|
||||
if ( ! elt_types->length() ||
|
||||
(*elt_types)[0]->Tag() != TYPE_RECORD )
|
||||
{
|
||||
ExprError("matching must be done against a set of match records");
|
||||
return;
|
||||
}
|
||||
|
||||
RecordType* case_rec_type = (*elt_types)[0]->AsRecordType();
|
||||
|
||||
// NOTE: The "result" and "pred" field names are hardcoded here.
|
||||
result_field_index = case_rec_type->FieldOffset("result");
|
||||
|
||||
if ( result_field_index < 0 )
|
||||
{
|
||||
ExprError("match records must have a $result field");
|
||||
return;
|
||||
}
|
||||
|
||||
result_type = case_rec_type->FieldType("result")->Ref();
|
||||
|
||||
// Check that pred exists, and that the first argument matches it.
|
||||
if ( (pred_field_index = case_rec_type->FieldOffset("pred")) < 0 ||
|
||||
case_rec_type->FieldType("pred")->Tag() != TYPE_FUNC )
|
||||
{
|
||||
ExprError("match records must have a $pred' field of function type");
|
||||
return;
|
||||
}
|
||||
|
||||
FuncType* pred_type = case_rec_type->FieldType("pred")->AsFuncType();
|
||||
type_list* pred_arg_types = pred_type->ArgTypes()->Types();
|
||||
if ( pred_arg_types->length() != 1 ||
|
||||
! check_and_promote_expr(op1, (*pred_arg_types)[0]) )
|
||||
ExprError("record to match does not have the same type as predicate argument");
|
||||
|
||||
// NOTE: The "priority" field name is hardcoded here.
|
||||
if ( (priority_field_index = case_rec_type->FieldOffset("priority")) >= 0 &&
|
||||
! IsArithmetic(case_rec_type->FieldType("priority")->Tag()) )
|
||||
ExprError("$priority field must have a numeric type");
|
||||
|
||||
SetType(result_type);
|
||||
}
|
||||
|
||||
void RecordMatchExpr::ExprDescribe(ODesc* d) const
|
||||
{
|
||||
if ( d->IsReadable() )
|
||||
{
|
||||
d->Add("match ");
|
||||
op1->Describe(d);
|
||||
d->Add(" using ");
|
||||
op2->Describe(d);
|
||||
}
|
||||
}
|
||||
|
||||
Val* RecordMatchExpr::Fold(Val* v1, Val* v2) const
|
||||
{
|
||||
TableVal* match_set = v2->AsTableVal();
|
||||
if ( ! match_set )
|
||||
Internal("non-table in RecordMatchExpr");
|
||||
|
||||
Val* return_val = 0;
|
||||
double highest_priority = -1e100;
|
||||
|
||||
ListVal* match_recs = match_set->ConvertToList(TYPE_ANY);
|
||||
for ( int i = 0; i < match_recs->Length(); ++i )
|
||||
{
|
||||
val_list args(1);
|
||||
args.append(v1->Ref());
|
||||
|
||||
double this_priority = 0;
|
||||
|
||||
// ### Get rid of the double Index if TYPE_ANY->TYPE_RECORD.
|
||||
Val* v = match_recs->Index(i)->AsListVal()->Index(0);
|
||||
|
||||
const RecordVal* match_rec = v->AsRecordVal();
|
||||
if ( ! match_rec )
|
||||
Internal("Element of match set is not a record");
|
||||
|
||||
if ( priority_field_index >= 0 )
|
||||
{
|
||||
this_priority =
|
||||
match_rec->Lookup(priority_field_index)->CoerceToDouble();
|
||||
if ( this_priority <= highest_priority )
|
||||
{
|
||||
Unref(v1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// No try/catch here; we pass exceptions upstream.
|
||||
Val* pred_val =
|
||||
match_rec->Lookup(pred_field_index)->AsFunc()->Call(&args);
|
||||
bool is_zero = pred_val->IsZero();
|
||||
Unref(pred_val);
|
||||
|
||||
if ( ! is_zero )
|
||||
{
|
||||
Val* new_return_val =
|
||||
match_rec->Lookup(result_field_index);
|
||||
|
||||
Unref(return_val);
|
||||
return_val = new_return_val->Ref();
|
||||
|
||||
if ( priority_field_index >= 0 )
|
||||
highest_priority = this_priority;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Unref(match_recs);
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIAL(RecordMatchExpr, SER_RECORD_MATCH_EXPR);
|
||||
|
||||
bool RecordMatchExpr::DoSerialize(SerialInfo* info) const
|
||||
{
|
||||
DO_SERIALIZE(SER_RECORD_MATCH_EXPR, BinaryExpr);
|
||||
return SERIALIZE(pred_field_index) && SERIALIZE(result_field_index) &&
|
||||
SERIALIZE(priority_field_index);
|
||||
}
|
||||
|
||||
bool RecordMatchExpr::DoUnserialize(UnserialInfo* info)
|
||||
{
|
||||
DO_UNSERIALIZE(BinaryExpr);
|
||||
return UNSERIALIZE(&pred_field_index) && UNSERIALIZE(&result_field_index) &&
|
||||
UNSERIALIZE(&priority_field_index);
|
||||
}
|
||||
|
||||
ArithCoerceExpr::ArithCoerceExpr(Expr* arg_op, TypeTag t)
|
||||
: UnaryExpr(EXPR_ARITH_COERCE, arg_op)
|
||||
{
|
||||
|
@ -4918,6 +4763,7 @@ Val* ListExpr::Eval(Frame* f) const
|
|||
if ( ! ev )
|
||||
{
|
||||
Error("uninitialized list value");
|
||||
Unref(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
26
src/Expr.h
26
src/Expr.h
|
@ -823,32 +823,6 @@ protected:
|
|||
string field_name;
|
||||
};
|
||||
|
||||
class RecordMatchExpr : public BinaryExpr {
|
||||
public:
|
||||
RecordMatchExpr(Expr* op1 /* record to match */,
|
||||
Expr* op2 /* cases to match against */);
|
||||
|
||||
protected:
|
||||
friend class Expr;
|
||||
RecordMatchExpr()
|
||||
{
|
||||
pred_field_index = result_field_index =
|
||||
priority_field_index = 0;
|
||||
}
|
||||
|
||||
virtual Val* Fold(Val* v1, Val* v2) const;
|
||||
void ExprDescribe(ODesc*) const;
|
||||
|
||||
DECLARE_SERIAL(RecordMatchExpr);
|
||||
|
||||
// The following are used to hold the field offset of
|
||||
// $pred, $result, $priority, so the names only need to
|
||||
// be looked up at compile-time.
|
||||
int pred_field_index;
|
||||
int result_field_index;
|
||||
int priority_field_index;
|
||||
};
|
||||
|
||||
class ArithCoerceExpr : public UnaryExpr {
|
||||
public:
|
||||
ArithCoerceExpr(Expr* op, TypeTag t);
|
||||
|
|
|
@ -232,7 +232,7 @@ BroFile::~BroFile()
|
|||
delete [] access;
|
||||
delete [] cipher_buffer;
|
||||
|
||||
#ifdef USE_PERFTOOLS
|
||||
#ifdef USE_PERFTOOLS_DEBUG
|
||||
heap_checker->UnIgnoreObject(this);
|
||||
#endif
|
||||
}
|
||||
|
@ -255,7 +255,7 @@ void BroFile::Init()
|
|||
cipher_ctx = 0;
|
||||
cipher_buffer = 0;
|
||||
|
||||
#ifdef USE_PERFTOOLS
|
||||
#ifdef USE_PERFTOOLS_DEBUG
|
||||
heap_checker->IgnoreObject(this);
|
||||
#endif
|
||||
}
|
||||
|
|
84
src/Frag.cc
84
src/Frag.cc
|
@ -27,21 +27,30 @@ void FragTimer::Dispatch(double t, int /* is_expire */)
|
|||
|
||||
FragReassembler::FragReassembler(NetSessions* arg_s,
|
||||
const IP_Hdr* ip, const u_char* pkt,
|
||||
uint32 frag_field, HashKey* k, double t)
|
||||
: Reassembler(0, ip->DstAddr(), REASSEM_IP)
|
||||
HashKey* k, double t)
|
||||
: Reassembler(0, REASSEM_IP)
|
||||
{
|
||||
s = arg_s;
|
||||
key = k;
|
||||
|
||||
const struct ip* ip4 = ip->IP4_Hdr();
|
||||
proto_hdr_len = ip4->ip_hl * 4;
|
||||
proto_hdr = (struct ip*) new u_char[64]; // max IP header + slop
|
||||
if ( ip4 )
|
||||
{
|
||||
proto_hdr_len = ip->HdrLen();
|
||||
proto_hdr = new u_char[64]; // max IP header + slop
|
||||
// Don't do a structure copy - need to pick up options, too.
|
||||
memcpy((void*) proto_hdr, (const void*) ip4, proto_hdr_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
proto_hdr_len = ip->HdrLen() - 8; // minus length of fragment header
|
||||
proto_hdr = new u_char[proto_hdr_len];
|
||||
memcpy(proto_hdr, ip->IP6_Hdr(), proto_hdr_len);
|
||||
}
|
||||
|
||||
reassembled_pkt = 0;
|
||||
frag_size = 0; // flag meaning "not known"
|
||||
|
||||
AddFragment(t, ip, pkt, frag_field);
|
||||
next_proto = ip->NextProto();
|
||||
|
||||
if ( frag_timeout != 0.0 )
|
||||
{
|
||||
|
@ -50,6 +59,8 @@ FragReassembler::FragReassembler(NetSessions* arg_s,
|
|||
}
|
||||
else
|
||||
expire_timer = 0;
|
||||
|
||||
AddFragment(t, ip, pkt);
|
||||
}
|
||||
|
||||
FragReassembler::~FragReassembler()
|
||||
|
@ -60,28 +71,42 @@ FragReassembler::~FragReassembler()
|
|||
delete key;
|
||||
}
|
||||
|
||||
void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt,
|
||||
uint32 frag_field)
|
||||
void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt)
|
||||
{
|
||||
const struct ip* ip4 = ip->IP4_Hdr();
|
||||
|
||||
if ( ip4->ip_p != proto_hdr->ip_p || ip4->ip_hl != proto_hdr->ip_hl )
|
||||
if ( ip4 )
|
||||
{
|
||||
if ( ip4->ip_p != ((const struct ip*)proto_hdr)->ip_p ||
|
||||
ip4->ip_hl != ((const struct ip*)proto_hdr)->ip_hl )
|
||||
// || ip4->ip_tos != proto_hdr->ip_tos
|
||||
// don't check TOS, there's at least one stack that actually
|
||||
// uses different values, and it's hard to see an associated
|
||||
// attack.
|
||||
s->Weird("fragment_protocol_inconsistency", ip);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ip->NextProto() != next_proto ||
|
||||
ip->HdrLen() - 8 != proto_hdr_len )
|
||||
s->Weird("fragment_protocol_inconsistency", ip);
|
||||
// TODO: more detailed unfrag header consistency checks?
|
||||
}
|
||||
|
||||
if ( frag_field & 0x4000 )
|
||||
if ( ip->DF() )
|
||||
// Linux MTU discovery for UDP can do this, for example.
|
||||
s->Weird("fragment_with_DF", ip);
|
||||
|
||||
int offset = (ntohs(ip4->ip_off) & 0x1fff) * 8;
|
||||
int len = ntohs(ip4->ip_len);
|
||||
int hdr_len = proto_hdr->ip_hl * 4;
|
||||
int offset = ip->FragOffset();
|
||||
int len = ip->TotalLen();
|
||||
int hdr_len = ip->HdrLen();
|
||||
int upper_seq = offset + len - hdr_len;
|
||||
|
||||
if ( (frag_field & 0x2000) == 0 )
|
||||
if ( ! offset )
|
||||
// Make sure to use the first fragment header's next field.
|
||||
next_proto = ip->NextProto();
|
||||
|
||||
if ( ! ip->MF() )
|
||||
{
|
||||
// Last fragment.
|
||||
if ( frag_size == 0 )
|
||||
|
@ -125,7 +150,7 @@ void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt,
|
|||
|
||||
void FragReassembler::Overlap(const u_char* b1, const u_char* b2, int n)
|
||||
{
|
||||
IP_Hdr proto_h((const struct ip*) proto_hdr);
|
||||
IP_Hdr proto_h(proto_hdr, false, proto_hdr_len);
|
||||
|
||||
if ( memcmp((const void*) b1, (const void*) b2, n) )
|
||||
s->Weird("fragment_inconsistency", &proto_h);
|
||||
|
@ -157,7 +182,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */)
|
|||
// can happen for benign reasons when we're
|
||||
// intermingling parts of two fragmented packets.
|
||||
|
||||
IP_Hdr proto_h((const struct ip*) proto_hdr);
|
||||
IP_Hdr proto_h(proto_hdr, false, proto_hdr_len);
|
||||
s->Weird("fragment_size_inconsistency", &proto_h);
|
||||
|
||||
// We decide to analyze the contiguous portion now.
|
||||
|
@ -171,7 +196,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */)
|
|||
|
||||
else if ( last_block->upper > frag_size )
|
||||
{
|
||||
IP_Hdr proto_h((const struct ip*) proto_hdr);
|
||||
IP_Hdr proto_h(proto_hdr, false, proto_hdr_len);
|
||||
s->Weird("fragment_size_inconsistency", &proto_h);
|
||||
frag_size = last_block->upper;
|
||||
}
|
||||
|
@ -193,8 +218,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */)
|
|||
u_char* pkt = new u_char[n];
|
||||
memcpy((void*) pkt, (const void*) proto_hdr, proto_hdr_len);
|
||||
|
||||
struct ip* reassem4 = (struct ip*) pkt;
|
||||
reassem4->ip_len = htons(frag_size + proto_hdr_len);
|
||||
u_char* pkt_start = pkt;
|
||||
|
||||
pkt += proto_hdr_len;
|
||||
|
||||
|
@ -214,7 +238,27 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */)
|
|||
}
|
||||
|
||||
delete reassembled_pkt;
|
||||
reassembled_pkt = new IP_Hdr(reassem4);
|
||||
|
||||
if ( ((const struct ip*)pkt_start)->ip_v == 4 )
|
||||
{
|
||||
struct ip* reassem4 = (struct ip*) pkt_start;
|
||||
reassem4->ip_len = htons(frag_size + proto_hdr_len);
|
||||
reassembled_pkt = new IP_Hdr(reassem4, true);
|
||||
}
|
||||
|
||||
else if ( ((const struct ip*)pkt_start)->ip_v == 6 )
|
||||
{
|
||||
struct ip6_hdr* reassem6 = (struct ip6_hdr*) pkt_start;
|
||||
reassem6->ip6_plen = htons(frag_size + proto_hdr_len - 40);
|
||||
const IPv6_Hdr_Chain* chain = new IPv6_Hdr_Chain(reassem6, next_proto, n);
|
||||
reassembled_pkt = new IP_Hdr(reassem6, true, n, chain);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
reporter->InternalError("bad IP version in fragment reassembly");
|
||||
}
|
||||
|
||||
|
||||
DeleteTimer();
|
||||
}
|
||||
|
|
|
@ -20,11 +20,10 @@ typedef void (FragReassembler::*frag_timer_func)(double t);
|
|||
class FragReassembler : public Reassembler {
|
||||
public:
|
||||
FragReassembler(NetSessions* s, const IP_Hdr* ip, const u_char* pkt,
|
||||
uint32 frag_field, HashKey* k, double t);
|
||||
HashKey* k, double t);
|
||||
~FragReassembler();
|
||||
|
||||
void AddFragment(double t, const IP_Hdr* ip, const u_char* pkt,
|
||||
uint32 frag_field);
|
||||
void AddFragment(double t, const IP_Hdr* ip, const u_char* pkt);
|
||||
|
||||
void Expire(double t);
|
||||
void DeleteTimer();
|
||||
|
@ -37,11 +36,12 @@ protected:
|
|||
void BlockInserted(DataBlock* start_block);
|
||||
void Overlap(const u_char* b1, const u_char* b2, int n);
|
||||
|
||||
struct ip* proto_hdr;
|
||||
u_char* proto_hdr;
|
||||
IP_Hdr* reassembled_pkt;
|
||||
int proto_hdr_len;
|
||||
NetSessions* s;
|
||||
int frag_size; // size of fully reassembled fragment
|
||||
uint16 next_proto; // first IPv6 fragment header's next proto field
|
||||
HashKey* key;
|
||||
|
||||
FragTimer* expire_timer;
|
||||
|
|
|
@ -42,6 +42,12 @@ Gnutella_Analyzer::Gnutella_Analyzer(Connection* conn)
|
|||
resp_msg_state = new GnutellaMsgState();
|
||||
}
|
||||
|
||||
Gnutella_Analyzer::~Gnutella_Analyzer()
|
||||
{
|
||||
delete orig_msg_state;
|
||||
delete resp_msg_state;
|
||||
}
|
||||
|
||||
void Gnutella_Analyzer::Done()
|
||||
{
|
||||
TCP_ApplicationAnalyzer::Done();
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
class Gnutella_Analyzer : public TCP_ApplicationAnalyzer {
|
||||
public:
|
||||
Gnutella_Analyzer(Connection* conn);
|
||||
~Gnutella_Analyzer();
|
||||
|
||||
virtual void Done ();
|
||||
virtual void DeliverStream(int len, const u_char* data, bool orig);
|
||||
|
|
|
@ -1543,7 +1543,7 @@ void HTTP_Analyzer::HTTP_Header(int is_orig, MIME_Header* h)
|
|||
}
|
||||
}
|
||||
|
||||
void HTTP_Analyzer::ParseVersion(data_chunk_t ver, const uint32* host,
|
||||
void HTTP_Analyzer::ParseVersion(data_chunk_t ver, const IPAddr& host,
|
||||
bool user_agent)
|
||||
{
|
||||
int len = ver.length;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "MIME.h"
|
||||
#include "binpac_bro.h"
|
||||
#include "ZIP.h"
|
||||
#include "IPAddr.h"
|
||||
|
||||
enum CHUNKED_TRANSFER_STATE {
|
||||
NON_CHUNKED_TRANSFER,
|
||||
|
@ -212,7 +213,7 @@ protected:
|
|||
|
||||
const BroString* UnansweredRequestMethod();
|
||||
|
||||
void ParseVersion(data_chunk_t ver, const uint32* host, bool user_agent);
|
||||
void ParseVersion(data_chunk_t ver, const IPAddr& host, bool user_agent);
|
||||
int HTTP_ReplyCode(const char* code_str);
|
||||
int ExpectReplyMessageBody();
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include "BroString.h"
|
||||
|
||||
#define UHASH_KEY_SIZE 32
|
||||
#define UHASH_KEY_SIZE 36
|
||||
|
||||
typedef uint64 hash_t;
|
||||
|
||||
|
|
550
src/ICMP.cc
550
src/ICMP.cc
|
@ -9,6 +9,8 @@
|
|||
#include "Event.h"
|
||||
#include "ICMP.h"
|
||||
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
ICMP_Analyzer::ICMP_Analyzer(Connection* c)
|
||||
: TransportLayerAnalyzer(AnalyzerTag::ICMP, c)
|
||||
{
|
||||
|
@ -32,7 +34,7 @@ void ICMP_Analyzer::Done()
|
|||
matcher_state.FinishEndpointMatcher();
|
||||
}
|
||||
|
||||
void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data,
|
||||
void ICMP_Analyzer::DeliverPacket(int len, const u_char* data,
|
||||
bool is_orig, int seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
assert(ip);
|
||||
|
@ -46,14 +48,34 @@ void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data,
|
|||
PacketContents(data + 8, min(len, caplen) - 8);
|
||||
|
||||
const struct icmp* icmpp = (const struct icmp*) data;
|
||||
len = arg_len;
|
||||
|
||||
if ( ! ignore_checksums && caplen >= len &&
|
||||
icmp_checksum(icmpp, len) != 0xffff )
|
||||
assert(caplen >= len); // Should have been caught earlier already.
|
||||
|
||||
if ( ! ignore_checksums )
|
||||
{
|
||||
int chksum = 0;
|
||||
|
||||
switch ( ip->NextProto() )
|
||||
{
|
||||
case IPPROTO_ICMP:
|
||||
chksum = icmp_checksum(icmpp, len);
|
||||
break;
|
||||
|
||||
case IPPROTO_ICMPV6:
|
||||
chksum = icmp6_checksum(icmpp, ip, len);
|
||||
break;
|
||||
|
||||
default:
|
||||
reporter->InternalError("unexpected IP proto in ICMP analyzer");
|
||||
break;
|
||||
}
|
||||
|
||||
if ( chksum != 0xffff )
|
||||
{
|
||||
Weird("bad_ICMP_checksum");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Conn()->SetLastTime(current_timestamp);
|
||||
|
||||
|
@ -77,7 +99,13 @@ void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data,
|
|||
else
|
||||
len_stat += len;
|
||||
|
||||
NextICMP(current_timestamp, icmpp, len, caplen, data);
|
||||
if ( ip->NextProto() == IPPROTO_ICMP )
|
||||
NextICMP4(current_timestamp, icmpp, len, caplen, data, ip);
|
||||
else if ( ip->NextProto() == IPPROTO_ICMPV6 )
|
||||
NextICMP6(current_timestamp, icmpp, len, caplen, data, ip);
|
||||
else
|
||||
reporter->InternalError("unexpected next protocol in ICMP::DeliverPacket()");
|
||||
|
||||
|
||||
if ( caplen >= len )
|
||||
ForwardPacket(len, data, is_orig, seq, ip, caplen);
|
||||
|
@ -87,26 +115,91 @@ void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data,
|
|||
false, false, true);
|
||||
}
|
||||
|
||||
void ICMP_Analyzer::NextICMP(double /* t */, const struct icmp* /* icmpp */,
|
||||
int /* len */, int /* caplen */,
|
||||
const u_char*& /* data */)
|
||||
void ICMP_Analyzer::NextICMP4(double t, const struct icmp* icmpp, int len, int caplen,
|
||||
const u_char*& data, const IP_Hdr* ip_hdr )
|
||||
{
|
||||
ICMPEvent(icmp_sent);
|
||||
switch ( icmpp->icmp_type )
|
||||
{
|
||||
case ICMP_ECHO:
|
||||
case ICMP_ECHOREPLY:
|
||||
Echo(t, icmpp, len, caplen, data, ip_hdr);
|
||||
break;
|
||||
|
||||
case ICMP_UNREACH:
|
||||
case ICMP_TIMXCEED:
|
||||
Context4(t, icmpp, len, caplen, data, ip_hdr);
|
||||
break;
|
||||
|
||||
default:
|
||||
ICMPEvent(icmp_sent, icmpp, len, 0, ip_hdr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ICMP_Analyzer::ICMPEvent(EventHandlerPtr f)
|
||||
void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int caplen,
|
||||
const u_char*& data, const IP_Hdr* ip_hdr )
|
||||
{
|
||||
switch ( icmpp->icmp_type )
|
||||
{
|
||||
// Echo types.
|
||||
case ICMP6_ECHO_REQUEST:
|
||||
case ICMP6_ECHO_REPLY:
|
||||
Echo(t, icmpp, len, caplen, data, ip_hdr);
|
||||
break;
|
||||
|
||||
// Error messages all have the same structure for their context,
|
||||
// and are handled by the same function.
|
||||
case ICMP6_PARAM_PROB:
|
||||
case ICMP6_TIME_EXCEEDED:
|
||||
case ICMP6_PACKET_TOO_BIG:
|
||||
case ICMP6_DST_UNREACH:
|
||||
Context6(t, icmpp, len, caplen, data, ip_hdr);
|
||||
break;
|
||||
|
||||
// Router related messages.
|
||||
case ND_REDIRECT:
|
||||
Redirect(t, icmpp, len, caplen, data, ip_hdr);
|
||||
break;
|
||||
case ND_ROUTER_ADVERT:
|
||||
RouterAdvert(t, icmpp, len, caplen, data, ip_hdr);
|
||||
break;
|
||||
case ND_NEIGHBOR_ADVERT:
|
||||
NeighborAdvert(t, icmpp, len, caplen, data, ip_hdr);
|
||||
break;
|
||||
case ND_NEIGHBOR_SOLICIT:
|
||||
NeighborSolicit(t, icmpp, len, caplen, data, ip_hdr);
|
||||
break;
|
||||
case ND_ROUTER_SOLICIT:
|
||||
case ICMP6_ROUTER_RENUMBERING:
|
||||
Router(t, icmpp, len, caplen, data, ip_hdr);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
// Currently not specifically implemented.
|
||||
case MLD_LISTENER_QUERY:
|
||||
case MLD_LISTENER_REPORT:
|
||||
case MLD_LISTENER_REDUCTION:
|
||||
#endif
|
||||
default:
|
||||
ICMPEvent(icmp_sent, icmpp, len, 1, ip_hdr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ICMP_Analyzer::ICMPEvent(EventHandlerPtr f, const struct icmp* icmpp,
|
||||
int len, int icmpv6, const IP_Hdr* ip_hdr)
|
||||
{
|
||||
if ( ! f )
|
||||
return;
|
||||
|
||||
val_list* vl = new val_list;
|
||||
vl->append(BuildConnVal());
|
||||
vl->append(BuildICMPVal());
|
||||
|
||||
vl->append(BuildICMPVal(icmpp, len, icmpv6, ip_hdr));
|
||||
ConnectionEvent(f, vl);
|
||||
}
|
||||
|
||||
RecordVal* ICMP_Analyzer::BuildICMPVal()
|
||||
RecordVal* ICMP_Analyzer::BuildICMPVal(const struct icmp* icmpp, int len,
|
||||
int icmpv6, const IP_Hdr* ip_hdr)
|
||||
{
|
||||
if ( ! icmp_conn_val )
|
||||
{
|
||||
|
@ -114,9 +207,11 @@ RecordVal* ICMP_Analyzer::BuildICMPVal()
|
|||
|
||||
icmp_conn_val->Assign(0, new AddrVal(Conn()->OrigAddr()));
|
||||
icmp_conn_val->Assign(1, new AddrVal(Conn()->RespAddr()));
|
||||
icmp_conn_val->Assign(2, new Val(type, TYPE_COUNT));
|
||||
icmp_conn_val->Assign(3, new Val(code, TYPE_COUNT));
|
||||
icmp_conn_val->Assign(2, new Val(icmpp->icmp_type, TYPE_COUNT));
|
||||
icmp_conn_val->Assign(3, new Val(icmpp->icmp_code, TYPE_COUNT));
|
||||
icmp_conn_val->Assign(4, new Val(len, TYPE_COUNT));
|
||||
icmp_conn_val->Assign(5, new Val(ip_hdr->TTL(), TYPE_COUNT));
|
||||
icmp_conn_val->Assign(6, new Val(icmpv6, TYPE_BOOL));
|
||||
}
|
||||
|
||||
Ref(icmp_conn_val);
|
||||
|
@ -124,55 +219,25 @@ RecordVal* ICMP_Analyzer::BuildICMPVal()
|
|||
return icmp_conn_val;
|
||||
}
|
||||
|
||||
RecordVal* ICMP_Analyzer::ExtractICMPContext(int len, const u_char*& data)
|
||||
TransportProto ICMP_Analyzer::GetContextProtocol(const IP_Hdr* ip_hdr, uint32* src_port, uint32* dst_port)
|
||||
{
|
||||
const struct ip* ip = (const struct ip *) data;
|
||||
uint32 ip_hdr_len = ip->ip_hl * 4;
|
||||
|
||||
uint32 ip_len, frag_offset;
|
||||
TransportProto proto = TRANSPORT_UNKNOWN;
|
||||
int DF, MF, bad_hdr_len, bad_checksum;
|
||||
uint32 src_addr, dst_addr;
|
||||
uint32 src_port, dst_port;
|
||||
|
||||
if ( ip_hdr_len < sizeof(struct ip) || ip_hdr_len > uint32(len) )
|
||||
{ // We don't have an entire IP header.
|
||||
bad_hdr_len = 1;
|
||||
ip_len = frag_offset = 0;
|
||||
DF = MF = bad_checksum = 0;
|
||||
src_addr = dst_addr = 0;
|
||||
src_port = dst_port = 0;
|
||||
}
|
||||
const u_char* transport_hdr;
|
||||
uint32 ip_hdr_len = ip_hdr->HdrLen();
|
||||
bool ip4 = ip_hdr->IP4_Hdr();
|
||||
|
||||
if ( ip4 )
|
||||
transport_hdr = ((u_char *) ip_hdr->IP4_Hdr() + ip_hdr_len);
|
||||
else
|
||||
{
|
||||
bad_hdr_len = 0;
|
||||
ip_len = ntohs(ip->ip_len);
|
||||
bad_checksum = ones_complement_checksum((void*) ip, ip_hdr_len, 0) != 0xffff;
|
||||
transport_hdr = ((u_char *) ip_hdr->IP6_Hdr() + ip_hdr_len);
|
||||
|
||||
src_addr = uint32(ip->ip_src.s_addr);
|
||||
dst_addr = uint32(ip->ip_dst.s_addr);
|
||||
TransportProto proto;
|
||||
|
||||
switch ( ip->ip_p ) {
|
||||
switch ( ip_hdr->NextProto() ) {
|
||||
case 1: proto = TRANSPORT_ICMP; break;
|
||||
case 6: proto = TRANSPORT_TCP; break;
|
||||
case 17: proto = TRANSPORT_UDP; break;
|
||||
|
||||
// Default uses TRANSPORT_UNKNOWN, per initialization above.
|
||||
}
|
||||
|
||||
uint32 frag_field = ntohs(ip->ip_off);
|
||||
DF = frag_field & 0x4000;
|
||||
MF = frag_field & 0x2000;
|
||||
frag_offset = frag_field & /* IP_OFFMASK not portable */ 0x1fff;
|
||||
const u_char* transport_hdr = ((u_char *) ip + ip_hdr_len);
|
||||
|
||||
if ( uint32(len) < ip_hdr_len + 4 )
|
||||
{
|
||||
// 4 above is the magic number meaning that both
|
||||
// port numbers are included in the ICMP.
|
||||
bad_hdr_len = 1;
|
||||
src_port = dst_port = 0;
|
||||
case 58: proto = TRANSPORT_ICMP; break;
|
||||
default: proto = TRANSPORT_UNKNOWN; break;
|
||||
}
|
||||
|
||||
switch ( proto ) {
|
||||
|
@ -181,33 +246,87 @@ RecordVal* ICMP_Analyzer::ExtractICMPContext(int len, const u_char*& data)
|
|||
const struct icmp* icmpp =
|
||||
(const struct icmp *) transport_hdr;
|
||||
bool is_one_way; // dummy
|
||||
src_port = ntohs(icmpp->icmp_type);
|
||||
dst_port = ntohs(ICMP_counterpart(icmpp->icmp_type,
|
||||
icmpp->icmp_code,
|
||||
is_one_way));
|
||||
}
|
||||
*src_port = ntohs(icmpp->icmp_type);
|
||||
|
||||
if ( ip4 )
|
||||
*dst_port = ntohs(ICMP4_counterpart(icmpp->icmp_type,
|
||||
icmpp->icmp_code, is_one_way));
|
||||
else
|
||||
*dst_port = ntohs(ICMP6_counterpart(icmpp->icmp_type,
|
||||
icmpp->icmp_code, is_one_way));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TRANSPORT_TCP:
|
||||
{
|
||||
const struct tcphdr* tp =
|
||||
(const struct tcphdr *) transport_hdr;
|
||||
src_port = ntohs(tp->th_sport);
|
||||
dst_port = ntohs(tp->th_dport);
|
||||
}
|
||||
*src_port = ntohs(tp->th_sport);
|
||||
*dst_port = ntohs(tp->th_dport);
|
||||
break;
|
||||
}
|
||||
|
||||
case TRANSPORT_UDP:
|
||||
{
|
||||
const struct udphdr* up =
|
||||
(const struct udphdr *) transport_hdr;
|
||||
src_port = ntohs(up->uh_sport);
|
||||
dst_port = ntohs(up->uh_dport);
|
||||
}
|
||||
*src_port = ntohs(up->uh_sport);
|
||||
*dst_port = ntohs(up->uh_dport);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
src_port = dst_port = ntohs(0);
|
||||
*src_port = *dst_port = ntohs(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data)
|
||||
{
|
||||
const IP_Hdr ip_hdr_data((const struct ip*) data, false);
|
||||
const IP_Hdr* ip_hdr = &ip_hdr_data;
|
||||
|
||||
uint32 ip_hdr_len = ip_hdr->HdrLen();
|
||||
|
||||
uint32 ip_len, frag_offset;
|
||||
TransportProto proto = TRANSPORT_UNKNOWN;
|
||||
int DF, MF, bad_hdr_len, bad_checksum;
|
||||
IPAddr src_addr, dst_addr;
|
||||
uint32 src_port, dst_port;
|
||||
|
||||
if ( len < (int)sizeof(struct ip) || ip_hdr_len > uint32(len) )
|
||||
{
|
||||
// We don't have an entire IP header.
|
||||
bad_hdr_len = 1;
|
||||
ip_len = frag_offset = 0;
|
||||
DF = MF = bad_checksum = 0;
|
||||
src_port = dst_port = 0;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
bad_hdr_len = 0;
|
||||
ip_len = ip_hdr->TotalLen();
|
||||
bad_checksum = (ones_complement_checksum((void*) ip_hdr->IP4_Hdr(), ip_hdr_len, 0) != 0xffff);
|
||||
|
||||
src_addr = ip_hdr->SrcAddr();
|
||||
dst_addr = ip_hdr->DstAddr();
|
||||
|
||||
DF = ip_hdr->DF();
|
||||
MF = ip_hdr->MF();
|
||||
frag_offset = ip_hdr->FragOffset();
|
||||
|
||||
if ( uint32(len) >= ip_hdr_len + 4 )
|
||||
proto = GetContextProtocol(ip_hdr, &src_port, &dst_port);
|
||||
else
|
||||
{
|
||||
// 4 above is the magic number meaning that both
|
||||
// port numbers are included in the ICMP.
|
||||
src_port = dst_port = 0;
|
||||
bad_hdr_len = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,8 +337,8 @@ RecordVal* ICMP_Analyzer::ExtractICMPContext(int len, const u_char*& data)
|
|||
id_val->Assign(1, new PortVal(src_port, proto));
|
||||
id_val->Assign(2, new AddrVal(dst_addr));
|
||||
id_val->Assign(3, new PortVal(dst_port, proto));
|
||||
iprec->Assign(0, id_val);
|
||||
|
||||
iprec->Assign(0, id_val);
|
||||
iprec->Assign(1, new Val(ip_len, TYPE_COUNT));
|
||||
iprec->Assign(2, new Val(proto, TYPE_COUNT));
|
||||
iprec->Assign(3, new Val(frag_offset, TYPE_COUNT));
|
||||
|
@ -231,6 +350,66 @@ RecordVal* ICMP_Analyzer::ExtractICMPContext(int len, const u_char*& data)
|
|||
return iprec;
|
||||
}
|
||||
|
||||
RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data)
|
||||
{
|
||||
int DF = 0, MF = 0, bad_hdr_len = 0;
|
||||
TransportProto proto = TRANSPORT_UNKNOWN;
|
||||
|
||||
IPAddr src_addr;
|
||||
IPAddr dst_addr;
|
||||
uint32 ip_len, frag_offset = 0;
|
||||
uint32 src_port, dst_port;
|
||||
|
||||
if ( len < (int)sizeof(struct ip6_hdr) )
|
||||
{
|
||||
bad_hdr_len = 1;
|
||||
ip_len = 0;
|
||||
src_port = dst_port = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const IP_Hdr ip_hdr_data((const struct ip6_hdr*) data, false, len);
|
||||
const IP_Hdr* ip_hdr = &ip_hdr_data;
|
||||
|
||||
ip_len = ip_hdr->TotalLen();
|
||||
src_addr = ip_hdr->SrcAddr();
|
||||
dst_addr = ip_hdr->DstAddr();
|
||||
frag_offset = ip_hdr->FragOffset();
|
||||
MF = ip_hdr->MF();
|
||||
DF = ip_hdr->DF();
|
||||
|
||||
if ( uint32(len) >= uint32(ip_hdr->HdrLen() + 4) )
|
||||
proto = GetContextProtocol(ip_hdr, &src_port, &dst_port);
|
||||
else
|
||||
{
|
||||
// 4 above is the magic number meaning that both
|
||||
// port numbers are included in the ICMP.
|
||||
src_port = dst_port = 0;
|
||||
bad_hdr_len = 1;
|
||||
}
|
||||
}
|
||||
|
||||
RecordVal* iprec = new RecordVal(icmp_context);
|
||||
RecordVal* id_val = new RecordVal(conn_id);
|
||||
|
||||
id_val->Assign(0, new AddrVal(src_addr));
|
||||
id_val->Assign(1, new PortVal(src_port, proto));
|
||||
id_val->Assign(2, new AddrVal(dst_addr));
|
||||
id_val->Assign(3, new PortVal(dst_port, proto));
|
||||
|
||||
iprec->Assign(0, id_val);
|
||||
iprec->Assign(1, new Val(ip_len, TYPE_COUNT));
|
||||
iprec->Assign(2, new Val(proto, TYPE_COUNT));
|
||||
iprec->Assign(3, new Val(frag_offset, TYPE_COUNT));
|
||||
iprec->Assign(4, new Val(bad_hdr_len, TYPE_BOOL));
|
||||
// bad_checksum is always false since IPv6 layer doesn't have a checksum.
|
||||
iprec->Assign(5, new Val(0, TYPE_BOOL));
|
||||
iprec->Assign(6, new Val(MF, TYPE_BOOL));
|
||||
iprec->Assign(7, new Val(DF, TYPE_BOOL));
|
||||
|
||||
return iprec;
|
||||
}
|
||||
|
||||
bool ICMP_Analyzer::IsReuse(double /* t */, const u_char* /* pkt */)
|
||||
{
|
||||
return 0;
|
||||
|
@ -243,7 +422,7 @@ void ICMP_Analyzer::Describe(ODesc* d) const
|
|||
d->Add(Conn()->LastTime());
|
||||
d->AddSP(")");
|
||||
|
||||
d->Add(dotted_addr(Conn()->OrigAddr()));
|
||||
d->Add(Conn()->OrigAddr());
|
||||
d->Add(".");
|
||||
d->Add(type);
|
||||
d->Add(".");
|
||||
|
@ -252,7 +431,7 @@ void ICMP_Analyzer::Describe(ODesc* d) const
|
|||
d->SP();
|
||||
d->AddSP("->");
|
||||
|
||||
d->Add(dotted_addr(Conn()->RespAddr()));
|
||||
d->Add(Conn()->RespAddr());
|
||||
}
|
||||
|
||||
void ICMP_Analyzer::UpdateConnVal(RecordVal *conn_val)
|
||||
|
@ -294,15 +473,20 @@ unsigned int ICMP_Analyzer::MemoryAllocation() const
|
|||
+ (icmp_conn_val ? icmp_conn_val->MemoryAllocation() : 0);
|
||||
}
|
||||
|
||||
ICMP_Echo_Analyzer::ICMP_Echo_Analyzer(Connection* c)
|
||||
: ICMP_Analyzer(AnalyzerTag::ICMP_Echo, c)
|
||||
{
|
||||
}
|
||||
|
||||
void ICMP_Echo_Analyzer::NextICMP(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data)
|
||||
void ICMP_Analyzer::Echo(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
{
|
||||
EventHandlerPtr f = type == ICMP_ECHO ? icmp_echo_request : icmp_echo_reply;
|
||||
// For handling all Echo related ICMP messages
|
||||
EventHandlerPtr f = 0;
|
||||
|
||||
if ( ip_hdr->NextProto() == IPPROTO_ICMPV6 )
|
||||
f = (icmpp->icmp_type == ICMP6_ECHO_REQUEST)
|
||||
? icmp_echo_request : icmp_echo_reply;
|
||||
else
|
||||
f = (icmpp->icmp_type == ICMP_ECHO)
|
||||
? icmp_echo_request : icmp_echo_reply;
|
||||
|
||||
if ( ! f )
|
||||
return;
|
||||
|
||||
|
@ -313,7 +497,7 @@ void ICMP_Echo_Analyzer::NextICMP(double t, const struct icmp* icmpp, int len,
|
|||
|
||||
val_list* vl = new val_list;
|
||||
vl->append(BuildConnVal());
|
||||
vl->append(BuildICMPVal());
|
||||
vl->append(BuildICMPVal(icmpp, len, ip_hdr->NextProto() != IPPROTO_ICMP, ip_hdr));
|
||||
vl->append(new Val(iid, TYPE_COUNT));
|
||||
vl->append(new Val(iseq, TYPE_COUNT));
|
||||
vl->append(new StringVal(payload));
|
||||
|
@ -321,66 +505,232 @@ void ICMP_Echo_Analyzer::NextICMP(double t, const struct icmp* icmpp, int len,
|
|||
ConnectionEvent(f, vl);
|
||||
}
|
||||
|
||||
ICMP_Redir_Analyzer::ICMP_Redir_Analyzer(Connection* c)
|
||||
: ICMP_Analyzer(AnalyzerTag::ICMP_Redir, c)
|
||||
{
|
||||
}
|
||||
|
||||
void ICMP_Redir_Analyzer::NextICMP(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data)
|
||||
void ICMP_Analyzer::RouterAdvert(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
{
|
||||
uint32 addr = ntohl(icmpp->icmp_hun.ih_void);
|
||||
EventHandlerPtr f = icmp_router_advertisement;
|
||||
uint32 reachable, retrans;
|
||||
|
||||
memcpy(&reachable, data, sizeof(reachable));
|
||||
memcpy(&retrans, data + sizeof(reachable), sizeof(retrans));
|
||||
|
||||
val_list* vl = new val_list;
|
||||
vl->append(BuildConnVal());
|
||||
vl->append(BuildICMPVal());
|
||||
vl->append(new AddrVal(htonl(addr)));
|
||||
vl->append(BuildICMPVal(icmpp, len, 1, ip_hdr));
|
||||
vl->append(new Val(icmpp->icmp_num_addrs, TYPE_COUNT)); // Cur Hop Limit
|
||||
vl->append(new Val(icmpp->icmp_wpa & 0x80, TYPE_BOOL)); // Managed
|
||||
vl->append(new Val(icmpp->icmp_wpa & 0x40, TYPE_BOOL)); // Other
|
||||
vl->append(new Val(icmpp->icmp_wpa & 0x20, TYPE_BOOL)); // Home Agent
|
||||
vl->append(new Val((icmpp->icmp_wpa & 0x18)>>3, TYPE_COUNT)); // Pref
|
||||
vl->append(new Val(icmpp->icmp_wpa & 0x04, TYPE_BOOL)); // Proxy
|
||||
vl->append(new Val(icmpp->icmp_wpa & 0x02, TYPE_COUNT)); // Reserved
|
||||
vl->append(new IntervalVal((double)ntohs(icmpp->icmp_lifetime), Seconds));
|
||||
vl->append(new IntervalVal((double)ntohl(reachable), Milliseconds));
|
||||
vl->append(new IntervalVal((double)ntohl(retrans), Milliseconds));
|
||||
|
||||
ConnectionEvent(icmp_redirect, vl);
|
||||
ConnectionEvent(f, vl);
|
||||
}
|
||||
|
||||
|
||||
void ICMP_Context_Analyzer::NextICMP(double t, const struct icmp* icmpp,
|
||||
int len, int caplen, const u_char*& data)
|
||||
void ICMP_Analyzer::NeighborAdvert(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
{
|
||||
EventHandlerPtr f = icmp_neighbor_advertisement;
|
||||
in6_addr tgtaddr;
|
||||
|
||||
memcpy(&tgtaddr.s6_addr, data, sizeof(tgtaddr.s6_addr));
|
||||
|
||||
val_list* vl = new val_list;
|
||||
vl->append(BuildConnVal());
|
||||
vl->append(BuildICMPVal(icmpp, len, 1, ip_hdr));
|
||||
vl->append(new Val(icmpp->icmp_num_addrs & 0x80, TYPE_BOOL)); // Router
|
||||
vl->append(new Val(icmpp->icmp_num_addrs & 0x40, TYPE_BOOL)); // Solicited
|
||||
vl->append(new Val(icmpp->icmp_num_addrs & 0x20, TYPE_BOOL)); // Override
|
||||
vl->append(new AddrVal(IPAddr(tgtaddr)));
|
||||
|
||||
ConnectionEvent(f, vl);
|
||||
}
|
||||
|
||||
|
||||
void ICMP_Analyzer::NeighborSolicit(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
{
|
||||
EventHandlerPtr f = icmp_neighbor_solicitation;
|
||||
in6_addr tgtaddr;
|
||||
|
||||
memcpy(&tgtaddr.s6_addr, data, sizeof(tgtaddr.s6_addr));
|
||||
|
||||
val_list* vl = new val_list;
|
||||
vl->append(BuildConnVal());
|
||||
vl->append(BuildICMPVal(icmpp, len, 1, ip_hdr));
|
||||
vl->append(new AddrVal(IPAddr(tgtaddr)));
|
||||
|
||||
ConnectionEvent(f, vl);
|
||||
}
|
||||
|
||||
|
||||
void ICMP_Analyzer::Redirect(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
{
|
||||
EventHandlerPtr f = icmp_redirect;
|
||||
in6_addr tgtaddr, dstaddr;
|
||||
|
||||
memcpy(&tgtaddr.s6_addr, data, sizeof(tgtaddr.s6_addr));
|
||||
memcpy(&dstaddr.s6_addr, data + sizeof(tgtaddr.s6_addr), sizeof(dstaddr.s6_addr));
|
||||
|
||||
val_list* vl = new val_list;
|
||||
vl->append(BuildConnVal());
|
||||
vl->append(BuildICMPVal(icmpp, len, 1, ip_hdr));
|
||||
vl->append(new AddrVal(IPAddr(tgtaddr)));
|
||||
vl->append(new AddrVal(IPAddr(dstaddr)));
|
||||
|
||||
ConnectionEvent(f, vl);
|
||||
}
|
||||
|
||||
|
||||
void ICMP_Analyzer::Router(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
{
|
||||
EventHandlerPtr f = 0;
|
||||
switch ( type ) {
|
||||
case ICMP_UNREACH: f = icmp_unreachable; break;
|
||||
case ICMP_TIMXCEED: f = icmp_time_exceeded; break;
|
||||
|
||||
switch ( icmpp->icmp_type )
|
||||
{
|
||||
case ND_ROUTER_SOLICIT:
|
||||
f = icmp_router_solicitation;
|
||||
break;
|
||||
case ICMP6_ROUTER_RENUMBERING:
|
||||
default:
|
||||
ICMPEvent(icmp_sent, icmpp, len, 1, ip_hdr);
|
||||
return;
|
||||
}
|
||||
|
||||
val_list* vl = new val_list;
|
||||
vl->append(BuildConnVal());
|
||||
vl->append(BuildICMPVal(icmpp, len, 1, ip_hdr));
|
||||
|
||||
ConnectionEvent(f, vl);
|
||||
}
|
||||
|
||||
|
||||
void ICMP_Analyzer::Context4(double t, const struct icmp* icmpp,
|
||||
int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
{
|
||||
EventHandlerPtr f = 0;
|
||||
|
||||
switch ( icmpp->icmp_type )
|
||||
{
|
||||
case ICMP_UNREACH:
|
||||
f = icmp_unreachable;
|
||||
break;
|
||||
|
||||
case ICMP_TIMXCEED:
|
||||
f = icmp_time_exceeded;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( f )
|
||||
{
|
||||
val_list* vl = new val_list;
|
||||
vl->append(BuildConnVal());
|
||||
vl->append(BuildICMPVal());
|
||||
vl->append(new Val(code, TYPE_COUNT));
|
||||
vl->append(ExtractICMPContext(caplen, data));
|
||||
|
||||
vl->append(BuildICMPVal(icmpp, len, 0, ip_hdr));
|
||||
vl->append(new Val(icmpp->icmp_code, TYPE_COUNT));
|
||||
vl->append(ExtractICMP4Context(caplen, data));
|
||||
ConnectionEvent(f, vl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ICMP_counterpart(int icmp_type, int icmp_code, bool& is_one_way)
|
||||
void ICMP_Analyzer::Context6(double t, const struct icmp* icmpp,
|
||||
int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||
{
|
||||
EventHandlerPtr f = 0;
|
||||
|
||||
switch ( icmpp->icmp_type )
|
||||
{
|
||||
case ICMP6_DST_UNREACH:
|
||||
f = icmp_unreachable;
|
||||
break;
|
||||
|
||||
case ICMP6_PARAM_PROB:
|
||||
f = icmp_parameter_problem;
|
||||
break;
|
||||
|
||||
case ICMP6_TIME_EXCEEDED:
|
||||
f = icmp_time_exceeded;
|
||||
break;
|
||||
|
||||
case ICMP6_PACKET_TOO_BIG:
|
||||
f = icmp_packet_too_big;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( f )
|
||||
{
|
||||
val_list* vl = new val_list;
|
||||
vl->append(BuildConnVal());
|
||||
vl->append(BuildICMPVal(icmpp, len, 1, ip_hdr));
|
||||
vl->append(new Val(icmpp->icmp_code, TYPE_COUNT));
|
||||
vl->append(ExtractICMP6Context(caplen, data));
|
||||
ConnectionEvent(f, vl);
|
||||
}
|
||||
}
|
||||
|
||||
int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way)
|
||||
{
|
||||
is_one_way = false;
|
||||
|
||||
// return the counterpart type if one exists. This allows us
|
||||
// Return the counterpart type if one exists. This allows us
|
||||
// to track corresponding ICMP requests/replies.
|
||||
// Note that for the two-way ICMP messages, icmp_code is
|
||||
// always 0 (RFC 792).
|
||||
switch ( icmp_type ) {
|
||||
case ICMP_ECHO: return ICMP_ECHOREPLY;
|
||||
case ICMP_ECHOREPLY: return ICMP_ECHO;
|
||||
|
||||
case ICMP_TSTAMP: return ICMP_TSTAMPREPLY;
|
||||
case ICMP_TSTAMPREPLY: return ICMP_TSTAMP;
|
||||
|
||||
case ICMP_IREQ: return ICMP_IREQREPLY;
|
||||
case ICMP_IREQREPLY: return ICMP_IREQ;
|
||||
|
||||
case ICMP_ROUTERSOLICIT: return ICMP_ROUTERADVERT;
|
||||
|
||||
case ICMP_MASKREQ: return ICMP_MASKREPLY;
|
||||
case ICMP_MASKREPLY: return ICMP_MASKREQ;
|
||||
|
||||
default: is_one_way = true; return icmp_code;
|
||||
}
|
||||
}
|
||||
|
||||
int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way)
|
||||
{
|
||||
is_one_way = false;
|
||||
|
||||
switch ( icmp_type ) {
|
||||
case ICMP6_ECHO_REQUEST: return ICMP6_ECHO_REPLY;
|
||||
case ICMP6_ECHO_REPLY: return ICMP6_ECHO_REQUEST;
|
||||
|
||||
case ND_ROUTER_SOLICIT: return ND_ROUTER_ADVERT;
|
||||
case ND_ROUTER_ADVERT: return ND_ROUTER_SOLICIT;
|
||||
|
||||
case ND_NEIGHBOR_SOLICIT: return ND_NEIGHBOR_ADVERT;
|
||||
case ND_NEIGHBOR_ADVERT: return ND_NEIGHBOR_SOLICIT;
|
||||
|
||||
case MLD_LISTENER_QUERY: return MLD_LISTENER_REPORT;
|
||||
case MLD_LISTENER_REPORT: return MLD_LISTENER_QUERY;
|
||||
|
||||
// ICMP node information query and response respectively (not defined in
|
||||
// icmp6.h)
|
||||
case 139: return 140;
|
||||
case 140: return 139;
|
||||
|
||||
// Home Agent Address Discovery Request Message and reply
|
||||
case 144: return 145;
|
||||
case 145: return 144;
|
||||
|
||||
// TODO: Add further counterparts.
|
||||
|
||||
default: is_one_way = true; return icmp_code;
|
||||
}
|
||||
}
|
||||
|
|
120
src/ICMP.h
120
src/ICMP.h
|
@ -33,21 +33,51 @@ protected:
|
|||
virtual bool IsReuse(double t, const u_char* pkt);
|
||||
virtual unsigned int MemoryAllocation() const;
|
||||
|
||||
void ICMPEvent(EventHandlerPtr f);
|
||||
void ICMPEvent(EventHandlerPtr f, const struct icmp* icmpp, int len,
|
||||
int icmpv6, const IP_Hdr* ip_hdr);
|
||||
|
||||
void Echo(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
|
||||
void Context(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
|
||||
void Redirect(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
|
||||
void RouterAdvert(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
|
||||
void NeighborAdvert(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
|
||||
void NeighborSolicit(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
|
||||
void Router(double t, const struct icmp* icmpp, int len,
|
||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
|
||||
|
||||
void Describe(ODesc* d) const;
|
||||
|
||||
RecordVal* BuildICMPVal();
|
||||
RecordVal* BuildICMPVal(const struct icmp* icmpp, int len, int icmpv6,
|
||||
const IP_Hdr* ip_hdr);
|
||||
|
||||
virtual void NextICMP(double t, const struct icmp* icmpp,
|
||||
int len, int caplen, const u_char*& data);
|
||||
void NextICMP4(double t, const struct icmp* icmpp, int len, int caplen,
|
||||
const u_char*& data, const IP_Hdr* ip_hdr );
|
||||
|
||||
RecordVal* ExtractICMPContext(int len, const u_char*& data);
|
||||
RecordVal* ExtractICMP4Context(int len, const u_char*& data);
|
||||
|
||||
void Context4(double t, const struct icmp* icmpp, int len, int caplen,
|
||||
const u_char*& data, const IP_Hdr* ip_hdr);
|
||||
|
||||
TransportProto GetContextProtocol(const IP_Hdr* ip_hdr, uint32* src_port,
|
||||
uint32* dst_port);
|
||||
|
||||
void NextICMP6(double t, const struct icmp* icmpp, int len, int caplen,
|
||||
const u_char*& data, const IP_Hdr* ip_hdr );
|
||||
|
||||
RecordVal* ExtractICMP6Context(int len, const u_char*& data);
|
||||
|
||||
void Context6(double t, const struct icmp* icmpp, int len, int caplen,
|
||||
const u_char*& data, const IP_Hdr* ip_hdr);
|
||||
|
||||
RecordVal* icmp_conn_val;
|
||||
int type;
|
||||
int code;
|
||||
int len;
|
||||
|
||||
int request_len, reply_len;
|
||||
|
||||
RuleMatcherState matcher_state;
|
||||
|
@ -56,81 +86,9 @@ private:
|
|||
void UpdateEndpointVal(RecordVal* endp, int is_orig);
|
||||
};
|
||||
|
||||
class ICMP_Echo_Analyzer : public ICMP_Analyzer {
|
||||
public:
|
||||
ICMP_Echo_Analyzer(Connection* conn);
|
||||
|
||||
static Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
{ return new ICMP_Echo_Analyzer(conn); }
|
||||
|
||||
static bool Available() { return icmp_echo_request || icmp_echo_reply; }
|
||||
|
||||
protected:
|
||||
ICMP_Echo_Analyzer() { }
|
||||
|
||||
virtual void NextICMP(double t, const struct icmp* icmpp,
|
||||
int len, int caplen, const u_char*& data);
|
||||
};
|
||||
|
||||
class ICMP_Redir_Analyzer : public ICMP_Analyzer {
|
||||
public:
|
||||
ICMP_Redir_Analyzer(Connection* conn);
|
||||
|
||||
static Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
{ return new ICMP_Redir_Analyzer(conn); }
|
||||
|
||||
static bool Available() { return icmp_redirect; }
|
||||
|
||||
protected:
|
||||
ICMP_Redir_Analyzer() { }
|
||||
|
||||
virtual void NextICMP(double t, const struct icmp* icmpp,
|
||||
int len, int caplen, const u_char*& data);
|
||||
};
|
||||
|
||||
class ICMP_Context_Analyzer : public ICMP_Analyzer {
|
||||
public:
|
||||
ICMP_Context_Analyzer(AnalyzerTag::Tag tag, Connection* conn)
|
||||
: ICMP_Analyzer(tag, conn) { }
|
||||
|
||||
protected:
|
||||
ICMP_Context_Analyzer() { }
|
||||
|
||||
virtual void NextICMP(double t, const struct icmp* icmpp,
|
||||
int len, int caplen, const u_char*& data);
|
||||
};
|
||||
|
||||
class ICMP_TimeExceeded_Analyzer : public ICMP_Context_Analyzer {
|
||||
public:
|
||||
ICMP_TimeExceeded_Analyzer(Connection* conn)
|
||||
: ICMP_Context_Analyzer(AnalyzerTag::ICMP_TimeExceeded, conn) { }
|
||||
|
||||
static Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
{ return new ICMP_TimeExceeded_Analyzer(conn); }
|
||||
|
||||
static bool Available() { return icmp_time_exceeded; }
|
||||
|
||||
protected:
|
||||
ICMP_TimeExceeded_Analyzer() { }
|
||||
};
|
||||
|
||||
class ICMP_Unreachable_Analyzer : public ICMP_Context_Analyzer {
|
||||
public:
|
||||
ICMP_Unreachable_Analyzer(Connection* conn)
|
||||
: ICMP_Context_Analyzer(AnalyzerTag::ICMP_Unreachable, conn) { }
|
||||
|
||||
static Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
{ return new ICMP_Unreachable_Analyzer(conn); }
|
||||
|
||||
static bool Available() { return icmp_unreachable; }
|
||||
|
||||
protected:
|
||||
ICMP_Unreachable_Analyzer() { }
|
||||
};
|
||||
|
||||
|
||||
// Returns the counterpart type to the given type (e.g., the counterpart
|
||||
// to ICMP_ECHOREPLY is ICMP_ECHO).
|
||||
extern int ICMP_counterpart(int icmp_type, int icmp_code, bool& is_one_way);
|
||||
extern int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way);
|
||||
extern int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -372,7 +372,7 @@ ID* ID::Unserialize(UnserialInfo* info)
|
|||
|
||||
Ref(id);
|
||||
global_scope()->Insert(id->Name(), id);
|
||||
#ifdef USE_PERFTOOLS
|
||||
#ifdef USE_PERFTOOLS_DEBUG
|
||||
heap_checker->IgnoreObject(id);
|
||||
#endif
|
||||
}
|
||||
|
|
627
src/IP.cc
Normal file
627
src/IP.cc
Normal file
|
@ -0,0 +1,627 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "IP.h"
|
||||
#include "Type.h"
|
||||
#include "Val.h"
|
||||
#include "Var.h"
|
||||
|
||||
static RecordType* ip4_hdr_type = 0;
|
||||
static RecordType* ip6_hdr_type = 0;
|
||||
static RecordType* ip6_ext_hdr_type = 0;
|
||||
static RecordType* ip6_option_type = 0;
|
||||
static RecordType* ip6_hopopts_type = 0;
|
||||
static RecordType* ip6_dstopts_type = 0;
|
||||
static RecordType* ip6_routing_type = 0;
|
||||
static RecordType* ip6_fragment_type = 0;
|
||||
static RecordType* ip6_ah_type = 0;
|
||||
static RecordType* ip6_esp_type = 0;
|
||||
static RecordType* ip6_mob_type = 0;
|
||||
static RecordType* ip6_mob_msg_type = 0;
|
||||
static RecordType* ip6_mob_brr_type = 0;
|
||||
static RecordType* ip6_mob_hoti_type = 0;
|
||||
static RecordType* ip6_mob_coti_type = 0;
|
||||
static RecordType* ip6_mob_hot_type = 0;
|
||||
static RecordType* ip6_mob_cot_type = 0;
|
||||
static RecordType* ip6_mob_bu_type = 0;
|
||||
static RecordType* ip6_mob_back_type = 0;
|
||||
static RecordType* ip6_mob_be_type = 0;
|
||||
|
||||
static inline RecordType* hdrType(RecordType*& type, const char* name)
|
||||
{
|
||||
if ( ! type )
|
||||
type = internal_type(name)->AsRecordType();
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static VectorVal* BuildOptionsVal(const u_char* data, int len)
|
||||
{
|
||||
VectorVal* vv = new VectorVal(new VectorType(
|
||||
hdrType(ip6_option_type, "ip6_option")->Ref()));
|
||||
|
||||
while ( len > 0 )
|
||||
{
|
||||
const struct ip6_opt* opt = (const struct ip6_opt*) data;
|
||||
RecordVal* rv = new RecordVal(ip6_option_type);
|
||||
rv->Assign(0, new Val(opt->ip6o_type, TYPE_COUNT));
|
||||
|
||||
if ( opt->ip6o_type == 0 )
|
||||
{
|
||||
// Pad1 option
|
||||
rv->Assign(1, new Val(0, TYPE_COUNT));
|
||||
rv->Assign(2, new StringVal(""));
|
||||
data += sizeof(uint8);
|
||||
len -= sizeof(uint8);
|
||||
}
|
||||
else
|
||||
{
|
||||
// PadN or other option
|
||||
uint16 off = 2 * sizeof(uint8);
|
||||
rv->Assign(1, new Val(opt->ip6o_len, TYPE_COUNT));
|
||||
rv->Assign(2, new StringVal(
|
||||
new BroString(data + off, opt->ip6o_len, 1)));
|
||||
data += opt->ip6o_len + off;
|
||||
len -= opt->ip6o_len + off;
|
||||
}
|
||||
|
||||
vv->Assign(vv->Size(), rv, 0);
|
||||
}
|
||||
|
||||
return vv;
|
||||
}
|
||||
|
||||
RecordVal* IPv6_Hdr::BuildRecordVal(VectorVal* chain) const
|
||||
{
|
||||
RecordVal* rv = 0;
|
||||
|
||||
switch ( type ) {
|
||||
case IPPROTO_IPV6:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_hdr_type, "ip6_hdr"));
|
||||
const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data;
|
||||
rv->Assign(0, new Val((ntohl(ip6->ip6_flow) & 0x0ff00000)>>20, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(ntohl(ip6->ip6_flow) & 0x000fffff, TYPE_COUNT));
|
||||
rv->Assign(2, new Val(ntohs(ip6->ip6_plen), TYPE_COUNT));
|
||||
rv->Assign(3, new Val(ip6->ip6_nxt, TYPE_COUNT));
|
||||
rv->Assign(4, new Val(ip6->ip6_hlim, TYPE_COUNT));
|
||||
rv->Assign(5, new AddrVal(IPAddr(ip6->ip6_src)));
|
||||
rv->Assign(6, new AddrVal(IPAddr(ip6->ip6_dst)));
|
||||
if ( ! chain )
|
||||
chain = new VectorVal(new VectorType(
|
||||
hdrType(ip6_ext_hdr_type, "ip6_ext_hdr")->Ref()));
|
||||
rv->Assign(7, chain);
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_HOPOPTS:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_hopopts_type, "ip6_hopopts"));
|
||||
const struct ip6_hbh* hbh = (const struct ip6_hbh*)data;
|
||||
rv->Assign(0, new Val(hbh->ip6h_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(hbh->ip6h_len, TYPE_COUNT));
|
||||
uint16 off = 2 * sizeof(uint8);
|
||||
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_DSTOPTS:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_dstopts_type, "ip6_dstopts"));
|
||||
const struct ip6_dest* dst = (const struct ip6_dest*)data;
|
||||
rv->Assign(0, new Val(dst->ip6d_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(dst->ip6d_len, TYPE_COUNT));
|
||||
uint16 off = 2 * sizeof(uint8);
|
||||
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_ROUTING:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_routing_type, "ip6_routing"));
|
||||
const struct ip6_rthdr* rt = (const struct ip6_rthdr*)data;
|
||||
rv->Assign(0, new Val(rt->ip6r_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(rt->ip6r_len, TYPE_COUNT));
|
||||
rv->Assign(2, new Val(rt->ip6r_type, TYPE_COUNT));
|
||||
rv->Assign(3, new Val(rt->ip6r_segleft, TYPE_COUNT));
|
||||
uint16 off = 4 * sizeof(uint8);
|
||||
rv->Assign(4, new StringVal(new BroString(data + off, Length() - off, 1)));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_FRAGMENT:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_fragment_type, "ip6_fragment"));
|
||||
const struct ip6_frag* frag = (const struct ip6_frag*)data;
|
||||
rv->Assign(0, new Val(frag->ip6f_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(frag->ip6f_reserved, TYPE_COUNT));
|
||||
rv->Assign(2, new Val((ntohs(frag->ip6f_offlg) & 0xfff8)>>3, TYPE_COUNT));
|
||||
rv->Assign(3, new Val((ntohs(frag->ip6f_offlg) & 0x0006)>>1, TYPE_COUNT));
|
||||
rv->Assign(4, new Val(ntohs(frag->ip6f_offlg) & 0x0001, TYPE_BOOL));
|
||||
rv->Assign(5, new Val(ntohl(frag->ip6f_ident), TYPE_COUNT));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_AH:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_ah_type, "ip6_ah"));
|
||||
rv->Assign(0, new Val(((ip6_ext*)data)->ip6e_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(((ip6_ext*)data)->ip6e_len, TYPE_COUNT));
|
||||
rv->Assign(2, new Val(ntohs(((uint16*)data)[1]), TYPE_COUNT));
|
||||
rv->Assign(3, new Val(ntohl(((uint32*)data)[1]), TYPE_COUNT));
|
||||
rv->Assign(4, new Val(ntohl(((uint32*)data)[2]), TYPE_COUNT));
|
||||
uint16 off = 3 * sizeof(uint32);
|
||||
rv->Assign(5, new StringVal(new BroString(data + off, Length() - off, 1)));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_ESP:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_esp_type, "ip6_esp"));
|
||||
const uint32* esp = (const uint32*)data;
|
||||
rv->Assign(0, new Val(ntohl(esp[0]), TYPE_COUNT));
|
||||
rv->Assign(1, new Val(ntohl(esp[1]), TYPE_COUNT));
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
case IPPROTO_MOBILITY:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_mob_type, "ip6_mobility_hdr"));
|
||||
const struct ip6_mobility* mob = (const struct ip6_mobility*) data;
|
||||
rv->Assign(0, new Val(mob->ip6mob_payload, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(mob->ip6mob_len, TYPE_COUNT));
|
||||
rv->Assign(2, new Val(mob->ip6mob_type, TYPE_COUNT));
|
||||
rv->Assign(3, new Val(mob->ip6mob_rsv, TYPE_COUNT));
|
||||
rv->Assign(4, new Val(ntohs(mob->ip6mob_chksum), TYPE_COUNT));
|
||||
|
||||
RecordVal* msg = new RecordVal(hdrType(ip6_mob_msg_type, "ip6_mobility_msg"));
|
||||
msg->Assign(0, new Val(mob->ip6mob_type, TYPE_COUNT));
|
||||
|
||||
uint16 off = sizeof(ip6_mobility);
|
||||
const u_char* msg_data = data + off;
|
||||
|
||||
switch ( mob->ip6mob_type ) {
|
||||
case 0:
|
||||
{
|
||||
RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_brr"));
|
||||
m->Assign(0, new Val(ntohs(*((uint16*)msg_data)), TYPE_COUNT));
|
||||
off += sizeof(uint16);
|
||||
m->Assign(1, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(1, m);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_hoti"));
|
||||
m->Assign(0, new Val(ntohs(*((uint16*)msg_data)), TYPE_COUNT));
|
||||
m->Assign(1, new Val(ntohll(*((uint64*)(msg_data + sizeof(uint16)))), TYPE_COUNT));
|
||||
off += sizeof(uint16) + sizeof(uint64);
|
||||
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(2, m);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_coti"));
|
||||
m->Assign(0, new Val(ntohs(*((uint16*)msg_data)), TYPE_COUNT));
|
||||
m->Assign(1, new Val(ntohll(*((uint64*)(msg_data + sizeof(uint16)))), TYPE_COUNT));
|
||||
off += sizeof(uint16) + sizeof(uint64);
|
||||
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(3, m);
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_hot"));
|
||||
m->Assign(0, new Val(ntohs(*((uint16*)msg_data)), TYPE_COUNT));
|
||||
m->Assign(1, new Val(ntohll(*((uint64*)(msg_data + sizeof(uint16)))), TYPE_COUNT));
|
||||
m->Assign(2, new Val(ntohll(*((uint64*)(msg_data + sizeof(uint16) + sizeof(uint64)))), TYPE_COUNT));
|
||||
off += sizeof(uint16) + 2 * sizeof(uint64);
|
||||
m->Assign(3, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(4, m);
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_cot"));
|
||||
m->Assign(0, new Val(ntohs(*((uint16*)msg_data)), TYPE_COUNT));
|
||||
m->Assign(1, new Val(ntohll(*((uint64*)(msg_data + sizeof(uint16)))), TYPE_COUNT));
|
||||
m->Assign(2, new Val(ntohll(*((uint64*)(msg_data + sizeof(uint16) + sizeof(uint64)))), TYPE_COUNT));
|
||||
off += sizeof(uint16) + 2 * sizeof(uint64);
|
||||
m->Assign(3, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(5, m);
|
||||
break;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_bu"));
|
||||
m->Assign(0, new Val(ntohs(*((uint16*)msg_data)), TYPE_COUNT));
|
||||
m->Assign(1, new Val(ntohs(*((uint16*)(msg_data + sizeof(uint16)))) & 0x8000, TYPE_BOOL));
|
||||
m->Assign(2, new Val(ntohs(*((uint16*)(msg_data + sizeof(uint16)))) & 0x4000, TYPE_BOOL));
|
||||
m->Assign(3, new Val(ntohs(*((uint16*)(msg_data + sizeof(uint16)))) & 0x2000, TYPE_BOOL));
|
||||
m->Assign(4, new Val(ntohs(*((uint16*)(msg_data + sizeof(uint16)))) & 0x1000, TYPE_BOOL));
|
||||
m->Assign(5, new Val(ntohs(*((uint16*)(msg_data + 2*sizeof(uint16)))), TYPE_COUNT));
|
||||
off += 3 * sizeof(uint16);
|
||||
m->Assign(6, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(6, m);
|
||||
break;
|
||||
}
|
||||
|
||||
case 6:
|
||||
{
|
||||
RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_back"));
|
||||
m->Assign(0, new Val(*((uint8*)msg_data), TYPE_COUNT));
|
||||
m->Assign(1, new Val(*((uint8*)(msg_data + sizeof(uint8))) & 0x80, TYPE_BOOL));
|
||||
m->Assign(2, new Val(ntohs(*((uint16*)(msg_data + sizeof(uint16)))), TYPE_COUNT));
|
||||
m->Assign(3, new Val(ntohs(*((uint16*)(msg_data + 2*sizeof(uint16)))), TYPE_COUNT));
|
||||
off += 3 * sizeof(uint16);
|
||||
m->Assign(4, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(7, m);
|
||||
break;
|
||||
}
|
||||
|
||||
case 7:
|
||||
{
|
||||
RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_be"));
|
||||
m->Assign(0, new Val(*((uint8*)msg_data), TYPE_COUNT));
|
||||
const in6_addr* hoa = (const in6_addr*)(msg_data + sizeof(uint16));
|
||||
m->Assign(1, new AddrVal(IPAddr(*hoa)));
|
||||
off += sizeof(uint16) + sizeof(in6_addr);
|
||||
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(8, m);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->Weird(fmt("unknown_mobility_type_%d", mob->ip6mob_type));
|
||||
break;
|
||||
}
|
||||
|
||||
rv->Assign(5, msg);
|
||||
}
|
||||
break;
|
||||
#endif //ENABLE_MOBILE_IPV6
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
RecordVal* IP_Hdr::BuildIPHdrVal() const
|
||||
{
|
||||
RecordVal* rval = 0;
|
||||
|
||||
if ( ip4 )
|
||||
{
|
||||
rval = new RecordVal(hdrType(ip4_hdr_type, "ip4_hdr"));
|
||||
rval->Assign(0, new Val(ip4->ip_hl * 4, TYPE_COUNT));
|
||||
rval->Assign(1, new Val(ip4->ip_tos, TYPE_COUNT));
|
||||
rval->Assign(2, new Val(ntohs(ip4->ip_len), TYPE_COUNT));
|
||||
rval->Assign(3, new Val(ntohs(ip4->ip_id), TYPE_COUNT));
|
||||
rval->Assign(4, new Val(ip4->ip_ttl, TYPE_COUNT));
|
||||
rval->Assign(5, new Val(ip4->ip_p, TYPE_COUNT));
|
||||
rval->Assign(6, new AddrVal(ip4->ip_src.s_addr));
|
||||
rval->Assign(7, new AddrVal(ip4->ip_dst.s_addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
rval = ((*ip6_hdrs)[0])->BuildRecordVal(ip6_hdrs->BuildVal());
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
RecordVal* IP_Hdr::BuildPktHdrVal() const
|
||||
{
|
||||
static RecordType* pkt_hdr_type = 0;
|
||||
static RecordType* tcp_hdr_type = 0;
|
||||
static RecordType* udp_hdr_type = 0;
|
||||
static RecordType* icmp_hdr_type = 0;
|
||||
|
||||
if ( ! pkt_hdr_type )
|
||||
{
|
||||
pkt_hdr_type = internal_type("pkt_hdr")->AsRecordType();
|
||||
tcp_hdr_type = internal_type("tcp_hdr")->AsRecordType();
|
||||
udp_hdr_type = internal_type("udp_hdr")->AsRecordType();
|
||||
icmp_hdr_type = internal_type("icmp_hdr")->AsRecordType();
|
||||
}
|
||||
|
||||
RecordVal* pkt_hdr = new RecordVal(pkt_hdr_type);
|
||||
|
||||
if ( ip4 )
|
||||
pkt_hdr->Assign(0, BuildIPHdrVal());
|
||||
else
|
||||
pkt_hdr->Assign(1, BuildIPHdrVal());
|
||||
|
||||
// L4 header.
|
||||
const u_char* data = Payload();
|
||||
|
||||
int proto = NextProto();
|
||||
switch ( proto ) {
|
||||
case IPPROTO_TCP:
|
||||
{
|
||||
const struct tcphdr* tp = (const struct tcphdr*) data;
|
||||
RecordVal* tcp_hdr = new RecordVal(tcp_hdr_type);
|
||||
|
||||
int tcp_hdr_len = tp->th_off * 4;
|
||||
int data_len = PayloadLen() - tcp_hdr_len;
|
||||
|
||||
tcp_hdr->Assign(0, new PortVal(ntohs(tp->th_sport), TRANSPORT_TCP));
|
||||
tcp_hdr->Assign(1, new PortVal(ntohs(tp->th_dport), TRANSPORT_TCP));
|
||||
tcp_hdr->Assign(2, new Val(uint32(ntohl(tp->th_seq)), TYPE_COUNT));
|
||||
tcp_hdr->Assign(3, new Val(uint32(ntohl(tp->th_ack)), TYPE_COUNT));
|
||||
tcp_hdr->Assign(4, new Val(tcp_hdr_len, TYPE_COUNT));
|
||||
tcp_hdr->Assign(5, new Val(data_len, TYPE_COUNT));
|
||||
tcp_hdr->Assign(6, new Val(tp->th_flags, TYPE_COUNT));
|
||||
tcp_hdr->Assign(7, new Val(ntohs(tp->th_win), TYPE_COUNT));
|
||||
|
||||
pkt_hdr->Assign(2, tcp_hdr);
|
||||
break;
|
||||
}
|
||||
|
||||
case IPPROTO_UDP:
|
||||
{
|
||||
const struct udphdr* up = (const struct udphdr*) data;
|
||||
RecordVal* udp_hdr = new RecordVal(udp_hdr_type);
|
||||
|
||||
udp_hdr->Assign(0, new PortVal(ntohs(up->uh_sport), TRANSPORT_UDP));
|
||||
udp_hdr->Assign(1, new PortVal(ntohs(up->uh_dport), TRANSPORT_UDP));
|
||||
udp_hdr->Assign(2, new Val(ntohs(up->uh_ulen), TYPE_COUNT));
|
||||
|
||||
pkt_hdr->Assign(3, udp_hdr);
|
||||
break;
|
||||
}
|
||||
|
||||
case IPPROTO_ICMP:
|
||||
{
|
||||
const struct icmp* icmpp = (const struct icmp *) data;
|
||||
RecordVal* icmp_hdr = new RecordVal(icmp_hdr_type);
|
||||
|
||||
icmp_hdr->Assign(0, new Val(icmpp->icmp_type, TYPE_COUNT));
|
||||
|
||||
pkt_hdr->Assign(4, icmp_hdr);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// This is not a protocol we understand.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pkt_hdr;
|
||||
}
|
||||
|
||||
static inline bool isIPv6ExtHeader(uint8 type)
|
||||
{
|
||||
switch (type) {
|
||||
case IPPROTO_HOPOPTS:
|
||||
case IPPROTO_ROUTING:
|
||||
case IPPROTO_DSTOPTS:
|
||||
case IPPROTO_FRAGMENT:
|
||||
case IPPROTO_AH:
|
||||
case IPPROTO_ESP:
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
case IPPROTO_MOBILITY:
|
||||
#endif
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, int total_len,
|
||||
bool set_next, uint16 next)
|
||||
{
|
||||
length = 0;
|
||||
uint8 current_type, next_type;
|
||||
next_type = IPPROTO_IPV6;
|
||||
const u_char* hdrs = (const u_char*) ip6;
|
||||
|
||||
if ( total_len < (int)sizeof(struct ip6_hdr) )
|
||||
reporter->InternalError("IPv6_HdrChain::Init with truncated IP header");
|
||||
|
||||
do
|
||||
{
|
||||
// We can't determine a given header's length if there's less than
|
||||
// two bytes of data available (2nd byte of extension headers is length)
|
||||
if ( total_len < 2 )
|
||||
return;
|
||||
|
||||
current_type = next_type;
|
||||
IPv6_Hdr* p = new IPv6_Hdr(current_type, hdrs);
|
||||
|
||||
next_type = p->NextHdr();
|
||||
uint16 cur_len = p->Length();
|
||||
|
||||
// If this header is truncated, don't add it to chain, don't go further.
|
||||
if ( cur_len > total_len )
|
||||
{
|
||||
delete p;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( set_next && next_type == IPPROTO_FRAGMENT )
|
||||
{
|
||||
p->ChangeNext(next);
|
||||
next_type = next;
|
||||
}
|
||||
|
||||
chain.push_back(p);
|
||||
|
||||
// Check for routing headers and remember final destination address.
|
||||
if ( current_type == IPPROTO_ROUTING )
|
||||
ProcessRoutingHeader((const struct ip6_rthdr*) hdrs, cur_len);
|
||||
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
// Only Mobile IPv6 has a destination option we care about right now.
|
||||
if ( current_type == IPPROTO_DSTOPTS )
|
||||
ProcessDstOpts((const struct ip6_dest*) hdrs, cur_len);
|
||||
#endif
|
||||
|
||||
hdrs += cur_len;
|
||||
length += cur_len;
|
||||
total_len -= cur_len;
|
||||
|
||||
} while ( current_type != IPPROTO_FRAGMENT &&
|
||||
current_type != IPPROTO_ESP &&
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
current_type != IPPROTO_MOBILITY &&
|
||||
#endif
|
||||
isIPv6ExtHeader(next_type) );
|
||||
}
|
||||
|
||||
void IPv6_Hdr_Chain::ProcessRoutingHeader(const struct ip6_rthdr* r, uint16 len)
|
||||
{
|
||||
if ( finalDst )
|
||||
{
|
||||
// RFC 2460 section 4.1 says Routing should occur at most once.
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "multiple_routing_headers");
|
||||
return;
|
||||
}
|
||||
|
||||
// Last 16 bytes of header (for all known types) is the address we want.
|
||||
const in6_addr* addr = (const in6_addr*)(((const u_char*)r) + len - 16);
|
||||
|
||||
switch ( r->ip6r_type ) {
|
||||
case 0: // Defined by RFC 2460, deprecated by RFC 5095
|
||||
{
|
||||
if ( r->ip6r_segleft > 0 && r->ip6r_len >= 2 )
|
||||
{
|
||||
if ( r->ip6r_len % 2 == 0 )
|
||||
finalDst = new IPAddr(*addr);
|
||||
else
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "odd_routing0_len");
|
||||
}
|
||||
|
||||
// Always raise a weird since this type is deprecated.
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "routing0_hdr");
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
case 2: // Defined by Mobile IPv6 RFC 6275.
|
||||
{
|
||||
if ( r->ip6r_segleft > 0 )
|
||||
{
|
||||
if ( r->ip6r_len == 2 )
|
||||
finalDst = new IPAddr(*addr);
|
||||
else
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "bad_routing2_len");
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
reporter->Weird(fmt("unknown_routing_type_%d", r->ip6r_type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
void IPv6_Hdr_Chain::ProcessDstOpts(const struct ip6_dest* d, uint16 len)
|
||||
{
|
||||
const u_char* data = (const u_char*) d;
|
||||
len -= 2 * sizeof(uint8);
|
||||
data += 2* sizeof(uint8);
|
||||
|
||||
while ( len > 0 )
|
||||
{
|
||||
const struct ip6_opt* opt = (const struct ip6_opt*) data;
|
||||
switch ( opt->ip6o_type ) {
|
||||
case 201: // Home Address Option, Mobile IPv6 RFC 6275 section 6.3
|
||||
{
|
||||
if ( opt->ip6o_len == 16 )
|
||||
if ( homeAddr )
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "multiple_home_addr_opts");
|
||||
else
|
||||
homeAddr = new IPAddr(*((const in6_addr*)(data + 2)));
|
||||
else
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "bad_home_addr_len");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( opt->ip6o_type == 0 )
|
||||
{
|
||||
data += sizeof(uint8);
|
||||
len -= sizeof(uint8);
|
||||
}
|
||||
else
|
||||
{
|
||||
data += 2 * sizeof(uint8) + opt->ip6o_len;
|
||||
len -= 2 * sizeof(uint8) + opt->ip6o_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
VectorVal* IPv6_Hdr_Chain::BuildVal() const
|
||||
{
|
||||
if ( ! ip6_ext_hdr_type )
|
||||
{
|
||||
ip6_ext_hdr_type = internal_type("ip6_ext_hdr")->AsRecordType();
|
||||
ip6_hopopts_type = internal_type("ip6_hopopts")->AsRecordType();
|
||||
ip6_dstopts_type = internal_type("ip6_dstopts")->AsRecordType();
|
||||
ip6_routing_type = internal_type("ip6_routing")->AsRecordType();
|
||||
ip6_fragment_type = internal_type("ip6_fragment")->AsRecordType();
|
||||
ip6_ah_type = internal_type("ip6_ah")->AsRecordType();
|
||||
ip6_esp_type = internal_type("ip6_esp")->AsRecordType();
|
||||
ip6_mob_type = internal_type("ip6_mobility_hdr")->AsRecordType();
|
||||
}
|
||||
|
||||
VectorVal* rval = new VectorVal(new VectorType(ip6_ext_hdr_type->Ref()));
|
||||
|
||||
for ( size_t i = 1; i < chain.size(); ++i )
|
||||
{
|
||||
RecordVal* v = chain[i]->BuildRecordVal();
|
||||
RecordVal* ext_hdr = new RecordVal(ip6_ext_hdr_type);
|
||||
uint8 type = chain[i]->Type();
|
||||
ext_hdr->Assign(0, new Val(type, TYPE_COUNT));
|
||||
|
||||
switch (type) {
|
||||
case IPPROTO_HOPOPTS:
|
||||
ext_hdr->Assign(1, v);
|
||||
break;
|
||||
case IPPROTO_DSTOPTS:
|
||||
ext_hdr->Assign(2, v);
|
||||
break;
|
||||
case IPPROTO_ROUTING:
|
||||
ext_hdr->Assign(3, v);
|
||||
break;
|
||||
case IPPROTO_FRAGMENT:
|
||||
ext_hdr->Assign(4, v);
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
ext_hdr->Assign(5, v);
|
||||
break;
|
||||
case IPPROTO_ESP:
|
||||
ext_hdr->Assign(6, v);
|
||||
break;
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
case IPPROTO_MOBILITY:
|
||||
ext_hdr->Assign(7, v);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
reporter->InternalError("IPv6_Hdr_Chain bad header %d", type);
|
||||
break;
|
||||
}
|
||||
rval->Assign(rval->Size(), ext_hdr, 0);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
568
src/IP.h
568
src/IP.h
|
@ -4,67 +4,370 @@
|
|||
#define ip_h
|
||||
|
||||
#include "config.h"
|
||||
#include "net_util.h"
|
||||
#include "IPAddr.h"
|
||||
#include "Reporter.h"
|
||||
#include "Val.h"
|
||||
#include "Type.h"
|
||||
#include <vector>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
|
||||
#include <net_util.h>
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
|
||||
#ifndef IPPROTO_MOBILITY
|
||||
#define IPPROTO_MOBILITY 135
|
||||
#endif
|
||||
|
||||
struct ip6_mobility {
|
||||
uint8 ip6mob_payload;
|
||||
uint8 ip6mob_len;
|
||||
uint8 ip6mob_type;
|
||||
uint8 ip6mob_rsv;
|
||||
uint16 ip6mob_chksum;
|
||||
};
|
||||
|
||||
#endif //ENABLE_MOBILE_IPV6
|
||||
|
||||
/**
|
||||
* Base class for IPv6 header/extensions.
|
||||
*/
|
||||
class IPv6_Hdr {
|
||||
public:
|
||||
/**
|
||||
* Construct an IPv6 header or extension header from assigned type number.
|
||||
*/
|
||||
IPv6_Hdr(uint8 t, const u_char* d) : type(t), data(d) {}
|
||||
|
||||
/**
|
||||
* Replace the value of the next protocol field.
|
||||
*/
|
||||
void ChangeNext(uint8 next_type)
|
||||
{
|
||||
switch ( type ) {
|
||||
case IPPROTO_IPV6:
|
||||
((ip6_hdr*)data)->ip6_nxt = next_type;
|
||||
break;
|
||||
case IPPROTO_HOPOPTS:
|
||||
case IPPROTO_DSTOPTS:
|
||||
case IPPROTO_ROUTING:
|
||||
case IPPROTO_FRAGMENT:
|
||||
case IPPROTO_AH:
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
case IPPROTO_MOBILITY:
|
||||
#endif
|
||||
((ip6_ext*)data)->ip6e_nxt = next_type;
|
||||
break;
|
||||
case IPPROTO_ESP:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
~IPv6_Hdr() {}
|
||||
|
||||
/**
|
||||
* Returns the assigned IPv6 extension header type number of the header
|
||||
* that immediately follows this one.
|
||||
*/
|
||||
uint8 NextHdr() const
|
||||
{
|
||||
switch ( type ) {
|
||||
case IPPROTO_IPV6:
|
||||
return ((ip6_hdr*)data)->ip6_nxt;
|
||||
case IPPROTO_HOPOPTS:
|
||||
case IPPROTO_DSTOPTS:
|
||||
case IPPROTO_ROUTING:
|
||||
case IPPROTO_FRAGMENT:
|
||||
case IPPROTO_AH:
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
case IPPROTO_MOBILITY:
|
||||
#endif
|
||||
return ((ip6_ext*)data)->ip6e_nxt;
|
||||
case IPPROTO_ESP:
|
||||
default:
|
||||
return IPPROTO_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the header in bytes.
|
||||
*/
|
||||
uint16 Length() const
|
||||
{
|
||||
switch ( type ) {
|
||||
case IPPROTO_IPV6:
|
||||
return 40;
|
||||
case IPPROTO_HOPOPTS:
|
||||
case IPPROTO_DSTOPTS:
|
||||
case IPPROTO_ROUTING:
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
case IPPROTO_MOBILITY:
|
||||
#endif
|
||||
return 8 + 8 * ((ip6_ext*)data)->ip6e_len;
|
||||
case IPPROTO_FRAGMENT:
|
||||
return 8;
|
||||
case IPPROTO_AH:
|
||||
return 8 + 4 * ((ip6_ext*)data)->ip6e_len;
|
||||
case IPPROTO_ESP:
|
||||
return 8; //encrypted payload begins after 8 bytes
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the RFC 1700 et seq. IANA assigned number for the header.
|
||||
*/
|
||||
uint8 Type() const { return type; }
|
||||
|
||||
/**
|
||||
* Returns pointer to the start of where header structure resides in memory.
|
||||
*/
|
||||
const u_char* Data() const { return data; }
|
||||
|
||||
/**
|
||||
* Returns the script-layer record representation of the header.
|
||||
*/
|
||||
RecordVal* BuildRecordVal(VectorVal* chain = 0) const;
|
||||
|
||||
protected:
|
||||
uint8 type;
|
||||
const u_char* data;
|
||||
};
|
||||
|
||||
class IPv6_Hdr_Chain {
|
||||
public:
|
||||
/**
|
||||
* Initializes the header chain from an IPv6 header structure.
|
||||
*/
|
||||
IPv6_Hdr_Chain(const struct ip6_hdr* ip6, int len) :
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
homeAddr(0),
|
||||
#endif
|
||||
finalDst(0)
|
||||
{ Init(ip6, len, false); }
|
||||
|
||||
~IPv6_Hdr_Chain()
|
||||
{
|
||||
for ( size_t i = 0; i < chain.size(); ++i ) delete chain[i];
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
delete homeAddr;
|
||||
#endif
|
||||
delete finalDst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of headers in the chain.
|
||||
*/
|
||||
size_t Size() const { return chain.size(); }
|
||||
|
||||
/**
|
||||
* Returns the sum of the length of all headers in the chain in bytes.
|
||||
*/
|
||||
uint16 TotalLength() const { return length; }
|
||||
|
||||
/**
|
||||
* Accesses the header at the given location in the chain.
|
||||
*/
|
||||
const IPv6_Hdr* operator[](const size_t i) const { return chain[i]; }
|
||||
|
||||
/**
|
||||
* Returns whether the header chain indicates a fragmented packet.
|
||||
*/
|
||||
bool IsFragment() const
|
||||
{ return chain[chain.size()-1]->Type() == IPPROTO_FRAGMENT; }
|
||||
|
||||
/**
|
||||
* Returns pointer to fragment header structure if the chain contains one.
|
||||
*/
|
||||
const struct ip6_frag* GetFragHdr() const
|
||||
{ return IsFragment() ?
|
||||
(const struct ip6_frag*)chain[chain.size()-1]->Data(): 0; }
|
||||
|
||||
/**
|
||||
* If the header chain is a fragment, returns the offset in number of bytes
|
||||
* relative to the start of the Fragmentable Part of the original packet.
|
||||
*/
|
||||
uint16 FragOffset() const
|
||||
{ return IsFragment() ?
|
||||
(ntohs(GetFragHdr()->ip6f_offlg) & 0xfff8) : 0; }
|
||||
|
||||
/**
|
||||
* If the header chain is a fragment, returns the identification field.
|
||||
*/
|
||||
uint32 ID() const
|
||||
{ return IsFragment() ? ntohl(GetFragHdr()->ip6f_ident) : 0; }
|
||||
|
||||
/**
|
||||
* If the header chain is a fragment, returns the M (more fragments) flag.
|
||||
*/
|
||||
int MF() const
|
||||
{ return IsFragment() ?
|
||||
(ntohs(GetFragHdr()->ip6f_offlg) & 0x0001) != 0 : 0; }
|
||||
|
||||
/**
|
||||
* If the chain contains a Destination Options header with a Home Address
|
||||
* option as defined by Mobile IPv6 (RFC 6275), then return it, else
|
||||
* return the source address in the main IPv6 header.
|
||||
*/
|
||||
IPAddr SrcAddr() const
|
||||
{
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
if ( homeAddr )
|
||||
return IPAddr(*homeAddr);
|
||||
else
|
||||
#endif
|
||||
return IPAddr(((const struct ip6_hdr*)(chain[0]->Data()))->ip6_src);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the chain contains a Routing header with non-zero segments left,
|
||||
* then return the last address of the first such header, else return
|
||||
* the destination address of the main IPv6 header.
|
||||
*/
|
||||
IPAddr DstAddr() const
|
||||
{
|
||||
if ( finalDst )
|
||||
return IPAddr(*finalDst);
|
||||
else
|
||||
return IPAddr(((const struct ip6_hdr*)(chain[0]->Data()))->ip6_dst);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a vector of ip6_ext_hdr RecordVals that includes script-layer
|
||||
* representation of all extension headers in the chain.
|
||||
*/
|
||||
VectorVal* BuildVal() const;
|
||||
|
||||
protected:
|
||||
// for access to protected ctor that changes next header values that
|
||||
// point to a fragment
|
||||
friend class FragReassembler;
|
||||
|
||||
/**
|
||||
* Initializes the header chain from an IPv6 header structure, and replaces
|
||||
* the first next protocol pointer field that points to a fragment header.
|
||||
*/
|
||||
IPv6_Hdr_Chain(const struct ip6_hdr* ip6, uint16 next, int len) :
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
homeAddr(0),
|
||||
#endif
|
||||
finalDst(0)
|
||||
{ Init(ip6, len, true, next); }
|
||||
|
||||
/**
|
||||
* Initializes the header chain from an IPv6 header structure of a given
|
||||
* length, possibly setting the first next protocol pointer field that
|
||||
* points to a fragment header.
|
||||
*/
|
||||
void Init(const struct ip6_hdr* ip6, int total_len, bool set_next,
|
||||
uint16 next = 0);
|
||||
|
||||
/**
|
||||
* Process a routing header and allocate/remember the final destination
|
||||
* address if it has segments left and is a valid routing header.
|
||||
*/
|
||||
void ProcessRoutingHeader(const struct ip6_rthdr* r, uint16 len);
|
||||
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
/**
|
||||
* Inspect a Destination Option header's options for things we need to
|
||||
* remember, such as the Home Address option from Mobile IPv6.
|
||||
*/
|
||||
void ProcessDstOpts(const struct ip6_dest* d, uint16 len);
|
||||
#endif
|
||||
|
||||
vector<IPv6_Hdr*> chain;
|
||||
|
||||
/**
|
||||
* The summation of all header lengths in the chain in bytes.
|
||||
*/
|
||||
uint16 length;
|
||||
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
/**
|
||||
* Home Address of the packet's source as defined by Mobile IPv6 (RFC 6275).
|
||||
*/
|
||||
IPAddr* homeAddr;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The final destination address in chain's first Routing header that has
|
||||
* non-zero segments left.
|
||||
*/
|
||||
IPAddr* finalDst;
|
||||
};
|
||||
|
||||
/**
|
||||
* A class that wraps either an IPv4 or IPv6 packet and abstracts methods
|
||||
* for inquiring about common features between the two.
|
||||
*/
|
||||
class IP_Hdr {
|
||||
public:
|
||||
IP_Hdr(struct ip* arg_ip4)
|
||||
/**
|
||||
* Attempts to construct the header from some blob of data based on IP
|
||||
* version number. Caller must have already checked that the header
|
||||
* is not truncated.
|
||||
* @param p pointer to memory containing an IPv4 or IPv6 packet.
|
||||
* @param arg_del whether to take ownership of \a p pointer's memory.
|
||||
* @param len the length of data, in bytes, pointed to by \a p.
|
||||
*/
|
||||
IP_Hdr(const u_char* p, bool arg_del, int len)
|
||||
: ip4(0), ip6(0), del(arg_del), ip6_hdrs(0)
|
||||
{
|
||||
ip4 = arg_ip4;
|
||||
ip6 = 0;
|
||||
del = 1;
|
||||
|
||||
#ifdef BROv6
|
||||
src_addr[0] = src_addr[1] = src_addr[2] = 0;
|
||||
dst_addr[0] = dst_addr[1] = dst_addr[2] = 0;
|
||||
|
||||
src_addr[3] = ip4->ip_src.s_addr;
|
||||
dst_addr[3] = ip4->ip_dst.s_addr;
|
||||
#endif
|
||||
if ( ((const struct ip*)p)->ip_v == 4 )
|
||||
ip4 = (const struct ip*)p;
|
||||
else if ( ((const struct ip*)p)->ip_v == 6 )
|
||||
{
|
||||
ip6 = (const struct ip6_hdr*)p;
|
||||
ip6_hdrs = new IPv6_Hdr_Chain(ip6, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( arg_del )
|
||||
delete [] p;
|
||||
reporter->InternalError("bad IP version in IP_Hdr ctor");
|
||||
}
|
||||
}
|
||||
|
||||
IP_Hdr(const struct ip* arg_ip4)
|
||||
/**
|
||||
* Construct the header wrapper from an IPv4 packet. Caller must have
|
||||
* already checked that the header is not truncated.
|
||||
* @param arg_ip4 pointer to memory containing an IPv4 packet.
|
||||
* @param arg_del whether to take ownership of \a arg_ip4 pointer's memory.
|
||||
*/
|
||||
IP_Hdr(const struct ip* arg_ip4, bool arg_del)
|
||||
: ip4(arg_ip4), ip6(0), del(arg_del), ip6_hdrs(0)
|
||||
{
|
||||
ip4 = arg_ip4;
|
||||
ip6 = 0;
|
||||
del = 0;
|
||||
|
||||
#ifdef BROv6
|
||||
src_addr[0] = src_addr[1] = src_addr[2] = 0;
|
||||
dst_addr[0] = dst_addr[1] = dst_addr[2] = 0;
|
||||
|
||||
src_addr[3] = ip4->ip_src.s_addr;
|
||||
dst_addr[3] = ip4->ip_dst.s_addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
IP_Hdr(struct ip6_hdr* arg_ip6)
|
||||
/**
|
||||
* Construct the header wrapper from an IPv6 packet. Caller must have
|
||||
* already checked that the static IPv6 header is not truncated. If
|
||||
* the packet contains extension headers and they are truncated, that can
|
||||
* be checked afterwards by comparing \a len with \a TotalLen. E.g.
|
||||
* NetSessions::DoNextPacket does this to skip truncated packets.
|
||||
* @param arg_ip6 pointer to memory containing an IPv6 packet.
|
||||
* @param arg_del whether to take ownership of \a arg_ip6 pointer's memory.
|
||||
* @param len the packet's length in bytes.
|
||||
* @param c an already-constructed header chain to take ownership of.
|
||||
*/
|
||||
IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del, int len,
|
||||
const IPv6_Hdr_Chain* c = 0)
|
||||
: ip4(0), ip6(arg_ip6), del(arg_del),
|
||||
ip6_hdrs(c ? c : new IPv6_Hdr_Chain(ip6, len))
|
||||
{
|
||||
ip4 = 0;
|
||||
ip6 = arg_ip6;
|
||||
del = 1;
|
||||
|
||||
#ifdef BROv6
|
||||
memcpy(src_addr, ip6->ip6_src.s6_addr, 16);
|
||||
memcpy(dst_addr, ip6->ip6_dst.s6_addr, 16);
|
||||
#endif
|
||||
}
|
||||
|
||||
IP_Hdr(const struct ip6_hdr* arg_ip6)
|
||||
{
|
||||
ip4 = 0;
|
||||
ip6 = arg_ip6;
|
||||
del = 0;
|
||||
|
||||
#ifdef BROv6
|
||||
memcpy(src_addr, ip6->ip6_src.s6_addr, 16);
|
||||
memcpy(dst_addr, ip6->ip6_dst.s6_addr, 16);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~IP_Hdr()
|
||||
{
|
||||
if ( ip6 )
|
||||
delete ip6_hdrs;
|
||||
|
||||
if ( del )
|
||||
{
|
||||
if ( ip4 )
|
||||
|
@ -74,68 +377,175 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If an IPv4 packet is wrapped, return a pointer to it, else null.
|
||||
*/
|
||||
const struct ip* IP4_Hdr() const { return ip4; }
|
||||
|
||||
/**
|
||||
* If an IPv6 packet is wrapped, return a pointer to it, else null.
|
||||
*/
|
||||
const struct ip6_hdr* IP6_Hdr() const { return ip6; }
|
||||
|
||||
#ifdef BROv6
|
||||
const uint32* SrcAddr() const { return src_addr; }
|
||||
const uint32* DstAddr() const { return dst_addr; }
|
||||
#else
|
||||
const uint32* SrcAddr() const
|
||||
{ return ip4 ? &(ip4->ip_src.s_addr) : 0; }
|
||||
const uint32* DstAddr() const
|
||||
{ return ip4 ? &(ip4->ip_dst.s_addr) : 0; }
|
||||
#endif
|
||||
/**
|
||||
* Returns the source address held in the IP header.
|
||||
*/
|
||||
IPAddr IPHeaderSrcAddr() const
|
||||
{ return ip4 ? IPAddr(ip4->ip_src) : IPAddr(ip6->ip6_src); }
|
||||
|
||||
uint32 SrcAddr4() const { return ip4->ip_src.s_addr; }
|
||||
uint32 DstAddr4() const { return ip4->ip_dst.s_addr; }
|
||||
/**
|
||||
* Returns the destination address held in the IP header.
|
||||
*/
|
||||
IPAddr IPHeaderDstAddr() const
|
||||
{ return ip4 ? IPAddr(ip4->ip_dst) : IPAddr(ip6->ip6_dst); }
|
||||
|
||||
uint16 ID4() const { return ip4 ? ip4->ip_id : 0; }
|
||||
/**
|
||||
* For IPv4 or IPv6 headers that don't contain a Home Address option
|
||||
* (Mobile IPv6, RFC 6275), return source address held in the IP header.
|
||||
* For IPv6 headers that contain a Home Address option, return that address.
|
||||
*/
|
||||
IPAddr SrcAddr() const
|
||||
{ return ip4 ? IPAddr(ip4->ip_src) : ip6_hdrs->SrcAddr(); }
|
||||
|
||||
/**
|
||||
* For IPv4 or IPv6 headers that don't contain a Routing header with
|
||||
* non-zero segments left, return destination address held in the IP header.
|
||||
* For IPv6 headers with a Routing header that has non-zero segments left,
|
||||
* return the last address in the first such Routing header.
|
||||
*/
|
||||
IPAddr DstAddr() const
|
||||
{ return ip4 ? IPAddr(ip4->ip_dst) : ip6_hdrs->DstAddr(); }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the payload of the IP packet, usually an
|
||||
* upper-layer protocol.
|
||||
*/
|
||||
const u_char* Payload() const
|
||||
{
|
||||
if ( ip4 )
|
||||
return ((const u_char*) ip4) + ip4->ip_hl * 4;
|
||||
else
|
||||
return ((const u_char*) ip6) + 40;
|
||||
return ((const u_char*) ip6) + ip6_hdrs->TotalLength();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MOBILE_IPV6
|
||||
/**
|
||||
* Returns a pointer to the mobility header of the IP packet, if present,
|
||||
* else a null pointer.
|
||||
*/
|
||||
const ip6_mobility* MobilityHeader() const
|
||||
{
|
||||
if ( ip4 )
|
||||
return 0;
|
||||
else if ( (*ip6_hdrs)[ip6_hdrs->Size()-1]->Type() != IPPROTO_MOBILITY )
|
||||
return 0;
|
||||
else
|
||||
return (const ip6_mobility*)(*ip6_hdrs)[ip6_hdrs->Size()-1]->Data();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns the length of the IP packet's payload (length of packet minus
|
||||
* header length or, for IPv6, also minus length of all extension headers).
|
||||
*/
|
||||
uint16 PayloadLen() const
|
||||
{
|
||||
if ( ip4 )
|
||||
return ntohs(ip4->ip_len) - ip4->ip_hl * 4;
|
||||
else
|
||||
return ntohs(ip6->ip6_plen);
|
||||
return ntohs(ip6->ip6_plen) + 40 - ip6_hdrs->TotalLength();
|
||||
}
|
||||
|
||||
uint16 TotalLen() const
|
||||
{
|
||||
if ( ip4 )
|
||||
return ntohs(ip4->ip_len);
|
||||
else
|
||||
return ntohs(ip6->ip6_plen) + 40;
|
||||
}
|
||||
/**
|
||||
* Returns the length of the IP packet (length of headers and payload).
|
||||
*/
|
||||
uint32 TotalLen() const
|
||||
{ return ip4 ? ntohs(ip4->ip_len) : ntohs(ip6->ip6_plen) + 40; }
|
||||
|
||||
uint16 HdrLen() const { return ip4 ? ip4->ip_hl * 4 : 40; }
|
||||
/**
|
||||
* Returns length of IP packet header (includes extension headers for IPv6).
|
||||
*/
|
||||
uint16 HdrLen() const
|
||||
{ return ip4 ? ip4->ip_hl * 4 : ip6_hdrs->TotalLength(); }
|
||||
|
||||
/**
|
||||
* For IPv6 header chains, returns the type of the last header in the chain.
|
||||
*/
|
||||
uint8 LastHeader() const
|
||||
{ return ip4 ? IPPROTO_RAW :
|
||||
((*ip6_hdrs)[ip6_hdrs->Size()-1])->Type(); }
|
||||
|
||||
/**
|
||||
* Returns the protocol type of the IP packet's payload, usually an
|
||||
* upper-layer protocol. For IPv6, this returns the last (extension)
|
||||
* header's Next Header value.
|
||||
*/
|
||||
unsigned char NextProto() const
|
||||
{ return ip4 ? ip4->ip_p : ip6->ip6_nxt; }
|
||||
{ return ip4 ? ip4->ip_p :
|
||||
((*ip6_hdrs)[ip6_hdrs->Size()-1])->NextHdr(); }
|
||||
|
||||
/**
|
||||
* Returns the IPv4 Time to Live or IPv6 Hop Limit field.
|
||||
*/
|
||||
unsigned char TTL() const
|
||||
{ return ip4 ? ip4->ip_ttl : ip6->ip6_hlim; }
|
||||
uint16 FragField() const
|
||||
{ return ntohs(ip4 ? ip4->ip_off : 0); }
|
||||
|
||||
/**
|
||||
* Returns whether the IP header indicates this packet is a fragment.
|
||||
*/
|
||||
bool IsFragment() const
|
||||
{ return ip4 ? (ntohs(ip4->ip_off) & 0x3fff) != 0 :
|
||||
ip6_hdrs->IsFragment(); }
|
||||
|
||||
/**
|
||||
* Returns the fragment packet's offset in relation to the original
|
||||
* packet in bytes.
|
||||
*/
|
||||
uint16 FragOffset() const
|
||||
{ return ip4 ? (ntohs(ip4->ip_off) & 0x1fff) * 8 :
|
||||
ip6_hdrs->FragOffset(); }
|
||||
|
||||
/**
|
||||
* Returns the fragment packet's identification field.
|
||||
*/
|
||||
uint32 ID() const
|
||||
{ return ip4 ? ntohs(ip4->ip_id) : ip6_hdrs->ID(); }
|
||||
|
||||
/**
|
||||
* Returns whether a fragment packet's "More Fragments" field is set.
|
||||
*/
|
||||
int MF() const
|
||||
{ return ip4 ? (ntohs(ip4->ip_off) & 0x2000) != 0 : ip6_hdrs->MF(); }
|
||||
|
||||
/**
|
||||
* Returns whether a fragment packet's "Don't Fragment" field is set.
|
||||
* Note that IPv6 has no such field.
|
||||
*/
|
||||
int DF() const
|
||||
{ return ip4 ? ((ntohs(ip4->ip_off) & IP_DF) != 0) : 0; }
|
||||
uint16 IP_ID() const
|
||||
{ return ip4 ? (ntohs(ip4->ip_id)) : 0; }
|
||||
{ return ip4 ? ((ntohs(ip4->ip_off) & 0x4000) != 0) : 0; }
|
||||
|
||||
/**
|
||||
* Returns number of IP headers in packet (includes IPv6 extension headers).
|
||||
*/
|
||||
size_t NumHeaders() const
|
||||
{ return ip4 ? 1 : ip6_hdrs->Size(); }
|
||||
|
||||
/**
|
||||
* Returns an ip_hdr or ip6_hdr_chain RecordVal.
|
||||
*/
|
||||
RecordVal* BuildIPHdrVal() const;
|
||||
|
||||
/**
|
||||
* Returns a pkt_hdr RecordVal, which includes not only the IP header, but
|
||||
* also upper-layer (tcp/udp/icmp) headers.
|
||||
*/
|
||||
RecordVal* BuildPktHdrVal() const;
|
||||
|
||||
private:
|
||||
const struct ip* ip4;
|
||||
const struct ip6_hdr* ip6;
|
||||
#ifdef BROv6
|
||||
uint32 src_addr[NUM_ADDR_WORDS];
|
||||
uint32 dst_addr[NUM_ADDR_WORDS];
|
||||
#endif
|
||||
int del;
|
||||
bool del;
|
||||
const IPv6_Hdr_Chain* ip6_hdrs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
286
src/IPAddr.cc
Normal file
286
src/IPAddr.cc
Normal file
|
@ -0,0 +1,286 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "IPAddr.h"
|
||||
#include "Reporter.h"
|
||||
#include "Conn.h"
|
||||
#include "DPM.h"
|
||||
#include "bro_inet_ntop.h"
|
||||
|
||||
const uint8_t IPAddr::v4_mapped_prefix[12] = { 0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0xff, 0xff };
|
||||
|
||||
HashKey* BuildConnIDHashKey(const ConnID& id)
|
||||
{
|
||||
struct {
|
||||
in6_addr ip1;
|
||||
in6_addr ip2;
|
||||
uint16 port1;
|
||||
uint16 port2;
|
||||
} key;
|
||||
|
||||
// Lookup up connection based on canonical ordering, which is
|
||||
// the smaller of <src addr, src port> and <dst addr, dst port>
|
||||
// followed by the other.
|
||||
if ( id.is_one_way ||
|
||||
addr_port_canon_lt(id.src_addr, id.src_port, id.dst_addr, id.dst_port)
|
||||
)
|
||||
{
|
||||
key.ip1 = id.src_addr.in6;
|
||||
key.ip2 = id.dst_addr.in6;
|
||||
key.port1 = id.src_port;
|
||||
key.port2 = id.dst_port;
|
||||
}
|
||||
else
|
||||
{
|
||||
key.ip1 = id.dst_addr.in6;
|
||||
key.ip2 = id.src_addr.in6;
|
||||
key.port1 = id.dst_port;
|
||||
key.port2 = id.src_port;
|
||||
}
|
||||
|
||||
return new HashKey(&key, sizeof(key));
|
||||
}
|
||||
|
||||
HashKey* BuildExpectedConnHashKey(const ExpectedConn& c)
|
||||
{
|
||||
struct {
|
||||
in6_addr orig;
|
||||
in6_addr resp;
|
||||
uint16 resp_p;
|
||||
uint16 proto;
|
||||
} key;
|
||||
|
||||
key.orig = c.orig.in6;
|
||||
key.resp = c.resp.in6;
|
||||
key.resp_p = c.resp_p;
|
||||
key.proto = c.proto;
|
||||
|
||||
return new HashKey(&key, sizeof(key));
|
||||
}
|
||||
|
||||
void IPAddr::Mask(int top_bits_to_keep)
|
||||
{
|
||||
if ( top_bits_to_keep < 0 || top_bits_to_keep > 128 )
|
||||
{
|
||||
reporter->Error("Bad IPAddr::Mask value %d", top_bits_to_keep);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t tmp[4];
|
||||
memcpy(tmp, in6.s6_addr, sizeof(in6.s6_addr));
|
||||
|
||||
int word = 3;
|
||||
int bits_to_chop = 128 - top_bits_to_keep;
|
||||
|
||||
while ( bits_to_chop >= 32 )
|
||||
{
|
||||
tmp[word] = 0;
|
||||
--word;
|
||||
bits_to_chop -= 32;
|
||||
}
|
||||
|
||||
uint32_t w = ntohl(tmp[word]);
|
||||
w >>= bits_to_chop;
|
||||
w <<= bits_to_chop;
|
||||
tmp[word] = htonl(w);
|
||||
|
||||
memcpy(in6.s6_addr, tmp, sizeof(in6.s6_addr));
|
||||
}
|
||||
|
||||
void IPAddr::ReverseMask(int top_bits_to_chop)
|
||||
{
|
||||
if ( top_bits_to_chop < 0 || top_bits_to_chop > 128 )
|
||||
{
|
||||
reporter->Error("Bad IPAddr::ReverseMask value %d", top_bits_to_chop);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t tmp[4];
|
||||
memcpy(tmp, in6.s6_addr, sizeof(in6.s6_addr));
|
||||
|
||||
int word = 0;
|
||||
int bits_to_chop = top_bits_to_chop;
|
||||
|
||||
while ( bits_to_chop >= 32 )
|
||||
{
|
||||
tmp[word] = 0;
|
||||
++word;
|
||||
bits_to_chop -= 32;
|
||||
}
|
||||
|
||||
uint32_t w = ntohl(tmp[word]);
|
||||
w <<= bits_to_chop;
|
||||
w >>= bits_to_chop;
|
||||
tmp[word] = htonl(w);
|
||||
|
||||
memcpy(in6.s6_addr, tmp, sizeof(in6.s6_addr));
|
||||
}
|
||||
|
||||
void IPAddr::Init(const std::string& s)
|
||||
{
|
||||
if ( s.find(':') == std::string::npos ) // IPv4.
|
||||
{
|
||||
memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix));
|
||||
|
||||
// Parse the address directly instead of using inet_pton since
|
||||
// some platforms have more sensitive implementations than others
|
||||
// that can't e.g. handle leading zeroes.
|
||||
int a[4];
|
||||
int n = sscanf(s.c_str(), "%d.%d.%d.%d", a+0, a+1, a+2, a+3);
|
||||
|
||||
if ( n != 4 || a[0] < 0 || a[1] < 0 || a[2] < 0 || a[3] < 0 ||
|
||||
a[0] > 255 || a[1] > 255 || a[2] > 255 || a[3] > 255 )
|
||||
{
|
||||
reporter->Error("Bad IP address: %s", s.c_str());
|
||||
memset(in6.s6_addr, 0, sizeof(in6.s6_addr));
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t addr = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3];
|
||||
addr = htonl(addr);
|
||||
memcpy(&in6.s6_addr[12], &addr, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if ( inet_pton(AF_INET6, s.c_str(), in6.s6_addr) <=0 )
|
||||
{
|
||||
reporter->Error("Bad IP address: %s", s.c_str());
|
||||
memset(in6.s6_addr, 0, sizeof(in6.s6_addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string IPAddr::AsString() const
|
||||
{
|
||||
if ( GetFamily() == IPv4 )
|
||||
{
|
||||
char s[INET_ADDRSTRLEN];
|
||||
|
||||
if ( ! bro_inet_ntop(AF_INET, &in6.s6_addr[12], s, INET_ADDRSTRLEN) )
|
||||
return "<bad IPv4 address conversion";
|
||||
else
|
||||
return s;
|
||||
}
|
||||
else
|
||||
{
|
||||
char s[INET6_ADDRSTRLEN];
|
||||
|
||||
if ( ! bro_inet_ntop(AF_INET6, in6.s6_addr, s, INET6_ADDRSTRLEN) )
|
||||
return "<bad IPv6 address conversion";
|
||||
else
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
string IPAddr::AsHexString() const
|
||||
{
|
||||
char buf[33];
|
||||
|
||||
if ( GetFamily() == IPv4 )
|
||||
{
|
||||
uint32_t* p = (uint32_t*) &in6.s6_addr[12];
|
||||
snprintf(buf, sizeof(buf), "%08x", (uint32_t) ntohl(*p));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t* p = (uint32_t*) in6.s6_addr;
|
||||
snprintf(buf, sizeof(buf), "%08x%08x%08x%08x",
|
||||
(uint32_t) ntohl(p[0]), (uint32_t) ntohl(p[1]),
|
||||
(uint32_t) ntohl(p[2]), (uint32_t) ntohl(p[3]));
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
string IPAddr::PtrName() const
|
||||
{
|
||||
if ( GetFamily() == IPv4 )
|
||||
{
|
||||
char buf[256];
|
||||
uint32_t* p = (uint32_t*) &in6.s6_addr[12];
|
||||
uint32_t a = ntohl(*p);
|
||||
uint32_t a3 = (a >> 24) & 0xff;
|
||||
uint32_t a2 = (a >> 16) & 0xff;
|
||||
uint32_t a1 = (a >> 8) & 0xff;
|
||||
uint32_t a0 = a & 0xff;
|
||||
snprintf(buf, sizeof(buf), "%u.%u.%u.%u.in-addr.arpa", a0, a1, a2, a3);
|
||||
return buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
static const char hex_digit[] = "0123456789abcdef";
|
||||
string ptr_name("ip6.arpa");
|
||||
uint32_t* p = (uint32_t*) in6.s6_addr;
|
||||
|
||||
for ( unsigned int i = 0; i < 4; ++i )
|
||||
{
|
||||
uint32 a = ntohl(p[i]);
|
||||
for ( unsigned int j = 1; j <=8; ++j )
|
||||
{
|
||||
ptr_name.insert(0, 1, '.');
|
||||
ptr_name.insert(0, 1, hex_digit[(a >> (32-j*4)) & 0x0f]);
|
||||
}
|
||||
}
|
||||
|
||||
return ptr_name;
|
||||
}
|
||||
}
|
||||
|
||||
IPPrefix::IPPrefix(const in4_addr& in4, uint8_t length)
|
||||
: prefix(in4), length(96 + length)
|
||||
{
|
||||
if ( length > 32 )
|
||||
reporter->InternalError("Bad in4_addr IPPrefix length : %d", length);
|
||||
|
||||
prefix.Mask(this->length);
|
||||
}
|
||||
|
||||
IPPrefix::IPPrefix(const in6_addr& in6, uint8_t length)
|
||||
: prefix(in6), length(length)
|
||||
{
|
||||
if ( length > 128 )
|
||||
reporter->InternalError("Bad in6_addr IPPrefix length : %d", length);
|
||||
|
||||
prefix.Mask(this->length);
|
||||
}
|
||||
|
||||
IPPrefix::IPPrefix(const IPAddr& addr, uint8_t length)
|
||||
: prefix(addr)
|
||||
{
|
||||
if ( prefix.GetFamily() == IPv4 )
|
||||
{
|
||||
if ( length > 32 )
|
||||
reporter->InternalError("Bad IPAddr(v4) IPPrefix length : %d",
|
||||
length);
|
||||
|
||||
this->length = length + 96;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if ( length > 128 )
|
||||
reporter->InternalError("Bad IPAddr(v6) IPPrefix length : %d",
|
||||
length);
|
||||
|
||||
this->length = length;
|
||||
}
|
||||
|
||||
prefix.Mask(this->length);
|
||||
}
|
||||
|
||||
string IPPrefix::AsString() const
|
||||
{
|
||||
char l[16];
|
||||
|
||||
if ( prefix.GetFamily() == IPv4 )
|
||||
modp_uitoa10(length - 96, l);
|
||||
else
|
||||
modp_uitoa10(length, l);
|
||||
|
||||
return prefix.AsString() +"/" + l;
|
||||
}
|
||||
|
586
src/IPAddr.h
Normal file
586
src/IPAddr.h
Normal file
|
@ -0,0 +1,586 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#ifndef IPADDR_H
|
||||
#define IPADDR_H
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string>
|
||||
|
||||
#include "BroString.h"
|
||||
#include "Hash.h"
|
||||
#include "util.h"
|
||||
#include "Type.h"
|
||||
#include "threading/SerialTypes.h"
|
||||
|
||||
struct ConnID;
|
||||
class ExpectedConn;
|
||||
|
||||
typedef in_addr in4_addr;
|
||||
|
||||
/**
|
||||
* Class storing both IPv4 and IPv6 addresses.
|
||||
*/
|
||||
class IPAddr
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Address family.
|
||||
*/
|
||||
typedef IPFamily Family;
|
||||
|
||||
/**
|
||||
* Byte order.
|
||||
*/
|
||||
enum ByteOrder { Host, Network };
|
||||
|
||||
/**
|
||||
* Constructs the unspecified IPv6 address (all 128 bits zeroed).
|
||||
*/
|
||||
IPAddr()
|
||||
{
|
||||
memset(in6.s6_addr, 0, sizeof(in6.s6_addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an address instance from an IPv4 address.
|
||||
*
|
||||
* @param in6 The IPv6 address.
|
||||
*/
|
||||
explicit IPAddr(const in4_addr& in4)
|
||||
{
|
||||
memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix));
|
||||
memcpy(&in6.s6_addr[12], &in4.s_addr, sizeof(in4.s_addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an address instance from an IPv6 address.
|
||||
*
|
||||
* @param in6 The IPv6 address.
|
||||
*/
|
||||
explicit IPAddr(const in6_addr& arg_in6) : in6(arg_in6) { }
|
||||
|
||||
/**
|
||||
* Constructs an address instance from a string representation.
|
||||
*
|
||||
* @param s String containing an IP address as either a dotted IPv4
|
||||
* address or a hex IPv6 address.
|
||||
*/
|
||||
IPAddr(const std::string& s)
|
||||
{
|
||||
Init(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an address instance from a string representation.
|
||||
*
|
||||
* @param s ASCIIZ string containing an IP address as either a
|
||||
* dotted IPv4 address or a hex IPv6 address.
|
||||
*/
|
||||
IPAddr(const char* s)
|
||||
{
|
||||
Init(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an address instance from a string representation.
|
||||
*
|
||||
* @param s String containing an IP address as either a dotted IPv4
|
||||
* address or a hex IPv6 address.
|
||||
*/
|
||||
IPAddr(const BroString& s)
|
||||
{
|
||||
Init(s.CheckString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an address instance from a raw byte representation.
|
||||
*
|
||||
* @param family The address family.
|
||||
*
|
||||
* @param bytes A pointer to the raw byte representation. This must point
|
||||
* to 4 bytes if \a family is IPv4, and to 16 bytes if \a family is
|
||||
* IPv6.
|
||||
*
|
||||
* @param order Indicates whether the raw representation pointed to
|
||||
* by \a bytes is stored in network or host order.
|
||||
*/
|
||||
IPAddr(Family family, const uint32_t* bytes, ByteOrder order);
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
IPAddr(const IPAddr& other) : in6(other.in6) { };
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~IPAddr() { };
|
||||
|
||||
/**
|
||||
* Returns the address' family.
|
||||
*/
|
||||
Family GetFamily() const
|
||||
{
|
||||
if ( memcmp(in6.s6_addr, v4_mapped_prefix, 12) == 0 )
|
||||
return IPv4;
|
||||
else
|
||||
return IPv6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the address represents a loopback device.
|
||||
*/
|
||||
bool IsLoopback() const;
|
||||
|
||||
/**
|
||||
* Returns true if the address represents a multicast address.
|
||||
*/
|
||||
bool IsMulticast() const
|
||||
{
|
||||
if ( GetFamily() == IPv4 )
|
||||
return in6.s6_addr[12] == 224;
|
||||
else
|
||||
return in6.s6_addr[0] == 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the address represents a broadcast address.
|
||||
*/
|
||||
bool IsBroadcast() const
|
||||
{
|
||||
if ( GetFamily() == IPv4 )
|
||||
return ((in6.s6_addr[12] == 0xff) && (in6.s6_addr[13] == 0xff)
|
||||
&& (in6.s6_addr[14] == 0xff) && (in6.s6_addr[15] == 0xff));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the raw byte representation of the address.
|
||||
*
|
||||
* @param bytes The pointer to which \a bytes points will be set to
|
||||
* the address of the raw representation in network-byte order.
|
||||
* The return value indicates how many 32-bit words are valid starting at
|
||||
* that address. The pointer will be valid as long as the address instance
|
||||
* exists.
|
||||
*
|
||||
* @return The number of 32-bit words the raw representation uses. This
|
||||
* will be 1 for an IPv4 address and 4 for an IPv6 address.
|
||||
*/
|
||||
int GetBytes(const uint32_t** bytes) const
|
||||
{
|
||||
if ( GetFamily() == IPv4 )
|
||||
{
|
||||
*bytes = (uint32_t*) &in6.s6_addr[12];
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*bytes = (uint32_t*) in6.s6_addr;
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a copy of the IPv6 raw byte representation of the address.
|
||||
* If the internal address is IPv4, then the copied bytes use the
|
||||
* IPv4 to IPv6 address mapping to return a full 16 bytes.
|
||||
*
|
||||
* @param bytes The pointer to a memory location in which the
|
||||
* raw bytes of the address are to be copied in network byte-order.
|
||||
*/
|
||||
void CopyIPv6(uint32_t* bytes) const
|
||||
{
|
||||
memcpy(bytes, in6.s6_addr, sizeof(in6.s6_addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a copy of the IPv6 raw byte representation of the address.
|
||||
* @see CopyIPv6(uint32_t)
|
||||
*/
|
||||
void CopyIPv6(in6_addr* arg_in6) const
|
||||
{
|
||||
memcpy(arg_in6->s6_addr, in6.s6_addr, sizeof(in6.s6_addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a copy of the IPv4 raw byte representation of the address.
|
||||
* The caller should verify the address is of the IPv4 family type
|
||||
* beforehand. @see GetFamily().
|
||||
*
|
||||
* @param in4 The pointer to a memory location in which the raw bytes
|
||||
* of the address are to be copied in network byte-order.
|
||||
*/
|
||||
void CopyIPv4(in4_addr* in4) const
|
||||
{
|
||||
memcpy(&in4->s_addr, &in6.s6_addr[12], sizeof(in4->s_addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a key that can be used to lookup the IP Address in a hash
|
||||
* table. Passes ownership to caller.
|
||||
*/
|
||||
HashKey* GetHashKey() const
|
||||
{
|
||||
return new HashKey((void*)in6.s6_addr, sizeof(in6.s6_addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Masks out lower bits of the address.
|
||||
*
|
||||
* @param top_bits_to_keep The number of bits \a not to mask out,
|
||||
* counting from the highest order bit. The value is always
|
||||
* interpreted relative to the IPv6 bit width, even if the address
|
||||
* is IPv4. That means if compute ``192.168.1.2/16``, you need to
|
||||
* pass in 112 (i.e., 96 + 16). The value must be in the range from
|
||||
* 0 to 128.
|
||||
*/
|
||||
void Mask(int top_bits_to_keep);
|
||||
|
||||
/**
|
||||
* Masks out top bits of the address.
|
||||
*
|
||||
* @param top_bits_to_chop The number of bits to mask out, counting
|
||||
* from the highest order bit. The value is always interpreted relative
|
||||
* to the IPv6 bit width, even if the address is IPv4. So to mask out
|
||||
* the first 16 bits of an IPv4 address, pass in 112 (i.e., 96 + 16).
|
||||
* The value must be in the range from 0 to 128.
|
||||
*/
|
||||
void ReverseMask(int top_bits_to_chop);
|
||||
|
||||
/**
|
||||
* Assignment operator.
|
||||
*/
|
||||
IPAddr& operator=(const IPAddr& other)
|
||||
{
|
||||
// No self-assignment check here because it's correct without it and
|
||||
// makes the common case faster.
|
||||
in6 = other.in6;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bitwise OR operator returns the IP address resulting from the bitwise
|
||||
* OR operation on the raw bytes of this address with another.
|
||||
*/
|
||||
IPAddr operator|(const IPAddr& other)
|
||||
{
|
||||
in6_addr result;
|
||||
for ( int i = 0; i < 16; ++i )
|
||||
result.s6_addr[i] = this->in6.s6_addr[i] | other.in6.s6_addr[i];
|
||||
|
||||
return IPAddr(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the address. IPv4 addresses
|
||||
* will be returned in dotted representation, IPv6 addresses in
|
||||
* compressed hex.
|
||||
*/
|
||||
string AsString() const;
|
||||
|
||||
/**
|
||||
* Returns a host-order, plain hex string representation of the address.
|
||||
*/
|
||||
string AsHexString() const;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the address. This returns the
|
||||
* same as AsString().
|
||||
*/
|
||||
operator std::string() const { return AsString(); }
|
||||
|
||||
/**
|
||||
* Returns a reverse pointer name associated with the IP address.
|
||||
* For example, 192.168.0.1's reverse pointer is 1.0.168.192.in-addr.arpa.
|
||||
*/
|
||||
string PtrName() const;
|
||||
|
||||
/**
|
||||
* Comparison operator for IP address.
|
||||
*/
|
||||
friend bool operator==(const IPAddr& addr1, const IPAddr& addr2)
|
||||
{
|
||||
return memcmp(&addr1.in6, &addr2.in6, sizeof(in6_addr)) == 0;
|
||||
}
|
||||
|
||||
friend bool operator!=(const IPAddr& addr1, const IPAddr& addr2)
|
||||
{
|
||||
return ! (addr1 == addr2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparison operator IP addresses. This defines a well-defined order for
|
||||
* IP addresses. However, the order does not necessarily correspond to
|
||||
* their numerical values.
|
||||
*/
|
||||
friend bool operator<(const IPAddr& addr1, const IPAddr& addr2)
|
||||
{
|
||||
return memcmp(&addr1.in6, &addr2.in6, sizeof(in6_addr)) < 0;
|
||||
}
|
||||
|
||||
/** Converts the address into the type used internally by the
|
||||
* inter-thread communication.
|
||||
*/
|
||||
void ConvertToThreadingValue(threading::Value::addr_t* v) const;
|
||||
|
||||
friend HashKey* BuildConnIDHashKey(const ConnID& id);
|
||||
friend HashKey* BuildExpectedConnHashKey(const ExpectedConn& c);
|
||||
|
||||
unsigned int MemoryAllocation() const { return padded_sizeof(*this); }
|
||||
|
||||
private:
|
||||
friend class IPPrefix;
|
||||
|
||||
/**
|
||||
* Initializes an address instance from a string representation.
|
||||
*
|
||||
* @param s String containing an IP address as either a dotted IPv4
|
||||
* address or a hex IPv6 address.
|
||||
*/
|
||||
void Init(const std::string& s);
|
||||
|
||||
in6_addr in6; // IPv6 or v4-to-v6-mapped address
|
||||
|
||||
static const uint8_t v4_mapped_prefix[12]; // top 96 bits of v4-mapped-addr
|
||||
};
|
||||
|
||||
inline IPAddr::IPAddr(Family family, const uint32_t* bytes, ByteOrder order)
|
||||
{
|
||||
if ( family == IPv4 )
|
||||
{
|
||||
memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix));
|
||||
memcpy(&in6.s6_addr[12], bytes, sizeof(uint32_t));
|
||||
|
||||
if ( order == Host )
|
||||
{
|
||||
uint32_t* p = (uint32_t*) &in6.s6_addr[12];
|
||||
*p = htonl(*p);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
memcpy(in6.s6_addr, bytes, sizeof(in6.s6_addr));
|
||||
|
||||
if ( order == Host )
|
||||
{
|
||||
for ( unsigned int i = 0; i < 4; ++ i)
|
||||
{
|
||||
uint32_t* p = (uint32_t*) &in6.s6_addr[i*4];
|
||||
*p = htonl(*p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool IPAddr::IsLoopback() const
|
||||
{
|
||||
if ( GetFamily() == IPv4 )
|
||||
return in6.s6_addr[12] == 127;
|
||||
|
||||
else
|
||||
return ((in6.s6_addr[0] == 0) && (in6.s6_addr[1] == 0)
|
||||
&& (in6.s6_addr[2] == 0) && (in6.s6_addr[3] == 0)
|
||||
&& (in6.s6_addr[4] == 0) && (in6.s6_addr[5] == 0)
|
||||
&& (in6.s6_addr[6] == 0) && (in6.s6_addr[7] == 0)
|
||||
&& (in6.s6_addr[8] == 0) && (in6.s6_addr[9] == 0)
|
||||
&& (in6.s6_addr[10] == 0) && (in6.s6_addr[11] == 0)
|
||||
&& (in6.s6_addr[12] == 0) && (in6.s6_addr[13] == 0)
|
||||
&& (in6.s6_addr[14] == 0) && (in6.s6_addr[15] == 1));
|
||||
}
|
||||
|
||||
inline void IPAddr::ConvertToThreadingValue(threading::Value::addr_t* v) const
|
||||
{
|
||||
v->family = GetFamily();
|
||||
|
||||
switch ( v->family ) {
|
||||
|
||||
case IPv4:
|
||||
CopyIPv4(&v->in.in4);
|
||||
return;
|
||||
|
||||
case IPv6:
|
||||
CopyIPv6(&v->in.in6);
|
||||
return;
|
||||
|
||||
// Can't be reached.
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash key for a given ConnID. Passes ownership to caller.
|
||||
*/
|
||||
HashKey* BuildConnIDHashKey(const ConnID& id);
|
||||
|
||||
/**
|
||||
* Returns a hash key for a given ExpectedConn instance. Passes ownership to caller.
|
||||
*/
|
||||
HashKey* BuildExpectedConnHashKey(const ExpectedConn& c);
|
||||
|
||||
/**
|
||||
* Class storing both IPv4 and IPv6 prefixes
|
||||
* (i.e., \c 192.168.1.1/16 and \c FD00::/8.
|
||||
*/
|
||||
class IPPrefix
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs a prefix 0/0.
|
||||
*/
|
||||
IPPrefix() : length(0) {}
|
||||
|
||||
/**
|
||||
* Constructs a prefix instance from an IPv4 address and a prefix
|
||||
* length.
|
||||
*
|
||||
* @param in4 The IPv4 address.
|
||||
*
|
||||
* @param length The prefix length in the range from 0 to 32.
|
||||
*/
|
||||
IPPrefix(const in4_addr& in4, uint8_t length);
|
||||
|
||||
/**
|
||||
* Constructs a prefix instance from an IPv6 address and a prefix
|
||||
* length.
|
||||
*
|
||||
* @param in6 The IPv6 address.
|
||||
*
|
||||
* @param length The prefix length in the range from 0 to 128.
|
||||
*/
|
||||
IPPrefix(const in6_addr& in6, uint8_t length);
|
||||
|
||||
/**
|
||||
* Constructs a prefix instance from an IPAddr object and prefix length.
|
||||
*
|
||||
* @param addr The IP address.
|
||||
*
|
||||
* @param length The prefix length in the range from 0 to 128
|
||||
*/
|
||||
IPPrefix(const IPAddr& addr, uint8_t length);
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
IPPrefix(const IPPrefix& other)
|
||||
: prefix(other.prefix), length(other.length) { }
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~IPPrefix() { }
|
||||
|
||||
/**
|
||||
* Returns the prefix in the form of an IP address. The address will
|
||||
* have all bits not part of the prefixed set to zero.
|
||||
*/
|
||||
const IPAddr& Prefix() const { return prefix; }
|
||||
|
||||
/**
|
||||
* Returns the bit length of the prefix, relative to the 32 bits
|
||||
* of an IPv4 prefix or relative to the 128 bits of an IPv6 prefix.
|
||||
*/
|
||||
uint8_t Length() const
|
||||
{
|
||||
return prefix.GetFamily() == IPv4 ? length - 96 : length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bit length of the prefix always relative to a full
|
||||
* 128 bits of an IPv6 prefix (or IPv4 mapped to IPv6).
|
||||
*/
|
||||
uint8_t LengthIPv6() const { return length; }
|
||||
|
||||
/** Returns true if the given address is part of the prefix.
|
||||
*
|
||||
* @param addr The address to test.
|
||||
*/
|
||||
bool Contains(const IPAddr& addr) const
|
||||
{
|
||||
IPAddr p(addr);
|
||||
p.Mask(length);
|
||||
return p == prefix;
|
||||
}
|
||||
/**
|
||||
* Assignment operator.
|
||||
*/
|
||||
IPPrefix& operator=(const IPPrefix& other)
|
||||
{
|
||||
// No self-assignment check here because it's correct without it and
|
||||
// makes the common case faster.
|
||||
prefix = other.prefix;
|
||||
length = other.length;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the prefix. IPv4 addresses
|
||||
* will be returned in dotted representation, IPv6 addresses in
|
||||
* compressed hex.
|
||||
*/
|
||||
string AsString() const;
|
||||
|
||||
operator std::string() const { return AsString(); }
|
||||
|
||||
/**
|
||||
* Returns a key that can be used to lookup the IP Prefix in a hash
|
||||
* table. Passes ownership to caller.
|
||||
*/
|
||||
HashKey* GetHashKey() const
|
||||
{
|
||||
struct {
|
||||
in6_addr ip;
|
||||
uint32 len;
|
||||
} key;
|
||||
|
||||
key.ip = prefix.in6;
|
||||
key.len = Length();
|
||||
|
||||
return new HashKey(&key, sizeof(key));
|
||||
}
|
||||
|
||||
/** Converts the prefix into the type used internally by the
|
||||
* inter-thread communication.
|
||||
*/
|
||||
void ConvertToThreadingValue(threading::Value::subnet_t* v) const
|
||||
{
|
||||
v->length = length;
|
||||
prefix.ConvertToThreadingValue(&v->prefix);
|
||||
}
|
||||
|
||||
unsigned int MemoryAllocation() const { return padded_sizeof(*this); }
|
||||
|
||||
/**
|
||||
* Comparison operator for IP prefix.
|
||||
*/
|
||||
friend bool operator==(const IPPrefix& net1, const IPPrefix& net2)
|
||||
{
|
||||
return net1.Prefix() == net2.Prefix() && net1.Length() == net2.Length();
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparison operator IP prefixes. This defines a well-defined order for
|
||||
* IP prefix. However, the order does not necessarily corresponding to their
|
||||
* numerical values.
|
||||
*/
|
||||
friend bool operator<(const IPPrefix& net1, const IPPrefix& net2)
|
||||
{
|
||||
if ( net1.Prefix() < net2.Prefix() )
|
||||
return true;
|
||||
|
||||
else if ( net1.Prefix() == net2.Prefix() )
|
||||
return net1.Length() < net2.Length();
|
||||
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
IPAddr prefix; // We store it as an address with the non-prefix bits masked out via Mask().
|
||||
uint8_t length; // The bit length of the prefix relative to full IPv6 addr.
|
||||
};
|
||||
|
||||
#endif
|
142
src/LogMgr.h
142
src/LogMgr.h
|
@ -1,142 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
//
|
||||
// A class managing log writers and filters.
|
||||
|
||||
#ifndef LOGMGR_H
|
||||
#define LOGMGR_H
|
||||
|
||||
#include "Val.h"
|
||||
#include "EventHandler.h"
|
||||
#include "RemoteSerializer.h"
|
||||
|
||||
class SerializationFormat;
|
||||
|
||||
// Description of a log field.
|
||||
struct LogField {
|
||||
string name;
|
||||
TypeTag type;
|
||||
// inner type of sets
|
||||
TypeTag subtype;
|
||||
|
||||
LogField() { subtype = TYPE_VOID; }
|
||||
LogField(const LogField& other)
|
||||
: name(other.name), type(other.type), subtype(other.subtype) { }
|
||||
|
||||
// (Un-)serialize.
|
||||
bool Read(SerializationFormat* fmt);
|
||||
bool Write(SerializationFormat* fmt) const;
|
||||
};
|
||||
|
||||
// Values as logged by a writer.
|
||||
struct LogVal {
|
||||
TypeTag type;
|
||||
bool present; // False for unset fields.
|
||||
|
||||
// The following union is a subset of BroValUnion, including only the
|
||||
// types we can log directly.
|
||||
struct set_t { bro_int_t size; LogVal** vals; };
|
||||
typedef set_t vec_t;
|
||||
|
||||
union _val {
|
||||
bro_int_t int_val;
|
||||
bro_uint_t uint_val;
|
||||
uint32 addr_val[NUM_ADDR_WORDS];
|
||||
subnet_type subnet_val;
|
||||
double double_val;
|
||||
string* string_val;
|
||||
set_t set_val;
|
||||
vec_t vector_val;
|
||||
} val;
|
||||
|
||||
LogVal(TypeTag arg_type = TYPE_ERROR, bool arg_present = true)
|
||||
: type(arg_type), present(arg_present) {}
|
||||
~LogVal();
|
||||
|
||||
// (Un-)serialize.
|
||||
bool Read(SerializationFormat* fmt);
|
||||
bool Write(SerializationFormat* fmt) const;
|
||||
|
||||
// Returns true if the type can be logged the framework. If
|
||||
// `atomic_only` is true, will not permit composite types.
|
||||
static bool IsCompatibleType(BroType* t, bool atomic_only=false);
|
||||
|
||||
private:
|
||||
LogVal(const LogVal& other) { }
|
||||
};
|
||||
|
||||
class LogWriter;
|
||||
class RemoteSerializer;
|
||||
class RotationTimer;
|
||||
|
||||
class LogMgr {
|
||||
public:
|
||||
LogMgr();
|
||||
~LogMgr();
|
||||
|
||||
// These correspond to the BiFs visible on the scripting layer. The
|
||||
// actual BiFs just forward here.
|
||||
bool CreateStream(EnumVal* id, RecordVal* stream);
|
||||
bool EnableStream(EnumVal* id);
|
||||
bool DisableStream(EnumVal* id);
|
||||
bool AddFilter(EnumVal* id, RecordVal* filter);
|
||||
bool RemoveFilter(EnumVal* id, StringVal* name);
|
||||
bool RemoveFilter(EnumVal* id, string name);
|
||||
bool Write(EnumVal* id, RecordVal* columns);
|
||||
bool SetBuf(EnumVal* id, bool enabled); // Adjusts all writers.
|
||||
bool Flush(EnumVal* id); // Flushes all writers..
|
||||
|
||||
protected:
|
||||
friend class LogWriter;
|
||||
friend class RemoteSerializer;
|
||||
friend class RotationTimer;
|
||||
|
||||
//// Function also used by the RemoteSerializer.
|
||||
|
||||
// Takes ownership of fields.
|
||||
LogWriter* CreateWriter(EnumVal* id, EnumVal* writer, string path,
|
||||
int num_fields, LogField** fields);
|
||||
|
||||
// Takes ownership of values..
|
||||
bool Write(EnumVal* id, EnumVal* writer, string path,
|
||||
int num_fields, LogVal** vals);
|
||||
|
||||
// Announces all instantiated writers to peer.
|
||||
void SendAllWritersTo(RemoteSerializer::PeerID peer);
|
||||
|
||||
//// Functions safe to use by writers.
|
||||
|
||||
// Signals that a file has been rotated.
|
||||
bool FinishedRotation(LogWriter* writer, string new_name, string old_name,
|
||||
double open, double close, bool terminating);
|
||||
|
||||
// Reports an error for the given writer.
|
||||
void Error(LogWriter* writer, const char* msg);
|
||||
|
||||
// Deletes the values as passed into Write().
|
||||
void DeleteVals(int num_fields, LogVal** vals);
|
||||
|
||||
private:
|
||||
struct Filter;
|
||||
struct Stream;
|
||||
struct WriterInfo;
|
||||
|
||||
bool TraverseRecord(Stream* stream, Filter* filter, RecordType* rt,
|
||||
TableVal* include, TableVal* exclude, string path, list<int> indices);
|
||||
|
||||
LogVal** RecordToFilterVals(Stream* stream, Filter* filter,
|
||||
RecordVal* columns);
|
||||
|
||||
LogVal* ValToLogVal(Val* val, BroType* ty = 0);
|
||||
Stream* FindStream(EnumVal* id);
|
||||
void RemoveDisabledWriters(Stream* stream);
|
||||
void InstallRotationTimer(WriterInfo* winfo);
|
||||
void Rotate(WriterInfo* info);
|
||||
Filter* FindFilter(EnumVal* id, StringVal* filter);
|
||||
WriterInfo* FindWriter(LogWriter* writer);
|
||||
|
||||
vector<Stream *> streams; // Indexed by stream enum.
|
||||
};
|
||||
|
||||
extern LogMgr* log_mgr;
|
||||
|
||||
#endif
|
158
src/LogWriter.cc
158
src/LogWriter.cc
|
@ -1,158 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "util.h"
|
||||
#include "LogWriter.h"
|
||||
|
||||
LogWriter::LogWriter()
|
||||
{
|
||||
buf = 0;
|
||||
buf_len = 1024;
|
||||
buffering = true;
|
||||
disabled = false;
|
||||
}
|
||||
|
||||
LogWriter::~LogWriter()
|
||||
{
|
||||
if ( buf )
|
||||
free(buf);
|
||||
|
||||
for(int i = 0; i < num_fields; ++i)
|
||||
delete fields[i];
|
||||
|
||||
delete [] fields;
|
||||
}
|
||||
|
||||
bool LogWriter::Init(string arg_path, int arg_num_fields,
|
||||
const LogField* const * arg_fields)
|
||||
{
|
||||
path = arg_path;
|
||||
num_fields = arg_num_fields;
|
||||
fields = arg_fields;
|
||||
|
||||
if ( ! DoInit(arg_path, arg_num_fields, arg_fields) )
|
||||
{
|
||||
disabled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LogWriter::Write(int arg_num_fields, LogVal** vals)
|
||||
{
|
||||
// Double-check that the arguments match. If we get this from remote,
|
||||
// something might be mixed up.
|
||||
if ( num_fields != arg_num_fields )
|
||||
{
|
||||
DBG_LOG(DBG_LOGGING, "Number of fields don't match in LogWriter::Write() (%d vs. %d)",
|
||||
arg_num_fields, num_fields);
|
||||
|
||||
DeleteVals(vals);
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < num_fields; ++i )
|
||||
{
|
||||
if ( vals[i]->type != fields[i]->type )
|
||||
{
|
||||
DBG_LOG(DBG_LOGGING, "Field type doesn't match in LogWriter::Write() (%d vs. %d)",
|
||||
vals[i]->type, fields[i]->type);
|
||||
DeleteVals(vals);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool result = DoWrite(num_fields, fields, vals);
|
||||
|
||||
DeleteVals(vals);
|
||||
|
||||
if ( ! result )
|
||||
disabled = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LogWriter::SetBuf(bool enabled)
|
||||
{
|
||||
if ( enabled == buffering )
|
||||
// No change.
|
||||
return true;
|
||||
|
||||
buffering = enabled;
|
||||
|
||||
if ( ! DoSetBuf(enabled) )
|
||||
{
|
||||
disabled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LogWriter::Rotate(string rotated_path, double open,
|
||||
double close, bool terminating)
|
||||
{
|
||||
if ( ! DoRotate(rotated_path, open, close, terminating) )
|
||||
{
|
||||
disabled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LogWriter::Flush()
|
||||
{
|
||||
if ( ! DoFlush() )
|
||||
{
|
||||
disabled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LogWriter::Finish()
|
||||
{
|
||||
DoFinish();
|
||||
}
|
||||
|
||||
const char* LogWriter::Fmt(const char* format, ...)
|
||||
{
|
||||
if ( ! buf )
|
||||
buf = (char*) malloc(buf_len);
|
||||
|
||||
va_list al;
|
||||
va_start(al, format);
|
||||
int n = safe_vsnprintf(buf, buf_len, format, al);
|
||||
va_end(al);
|
||||
|
||||
if ( (unsigned int) n >= buf_len )
|
||||
{ // Not enough room, grow the buffer.
|
||||
buf_len = n + 32;
|
||||
buf = (char*) realloc(buf, buf_len);
|
||||
|
||||
// Is it portable to restart?
|
||||
va_start(al, format);
|
||||
n = safe_vsnprintf(buf, buf_len, format, al);
|
||||
va_end(al);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void LogWriter::Error(const char *msg)
|
||||
{
|
||||
log_mgr->Error(this, msg);
|
||||
}
|
||||
|
||||
void LogWriter::DeleteVals(LogVal** vals)
|
||||
{
|
||||
log_mgr->DeleteVals(num_fields, vals);
|
||||
}
|
||||
|
||||
bool LogWriter::FinishedRotation(string new_name, string old_name, double open,
|
||||
double close, bool terminating)
|
||||
{
|
||||
return log_mgr->FinishedRotation(this, new_name, old_name, open, close, terminating);
|
||||
}
|
192
src/LogWriter.h
192
src/LogWriter.h
|
@ -1,192 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
//
|
||||
// Interface API for a log writer backend. The LogMgr creates a separate
|
||||
// writer instance of pair of (writer type, output path).
|
||||
//
|
||||
// Note thay classes derived from LogWriter must be fully thread-safe and not
|
||||
// use any non-thread-safe Bro functionality (which includes almost
|
||||
// everything ...). In particular, do not use fmt() but LogWriter::Fmt()!.
|
||||
//
|
||||
// The one exception to this rule is the constructor: it is guaranteed to be
|
||||
// executed inside the main thread and can thus in particular access global
|
||||
// script variables.
|
||||
|
||||
#ifndef LOGWRITER_H
|
||||
#define LOGWRITER_H
|
||||
|
||||
#include "LogMgr.h"
|
||||
#include "BroString.h"
|
||||
|
||||
class LogWriter {
|
||||
public:
|
||||
LogWriter();
|
||||
virtual ~LogWriter();
|
||||
|
||||
//// Interface methods to interact with the writer. Note that these
|
||||
//// methods are not necessarily thread-safe and must be called only
|
||||
//// from the main thread (which will typically mean only from the
|
||||
//// LogMgr). In particular, they must not be called from the
|
||||
//// writer's derived implementation.
|
||||
|
||||
// One-time initialization of the writer to define the logged fields.
|
||||
// Interpretation of "path" is left to the writer, and will be
|
||||
// corresponding the value configured on the script-level.
|
||||
//
|
||||
// Returns false if an error occured, in which case the writer must
|
||||
// not be used further.
|
||||
//
|
||||
// The new instance takes ownership of "fields", and will delete them
|
||||
// when done.
|
||||
bool Init(string path, int num_fields, const LogField* const * fields);
|
||||
|
||||
// Writes one log entry. The method takes ownership of "vals" and
|
||||
// will return immediately after queueing the write request, which is
|
||||
// potentially before output has actually been written out.
|
||||
//
|
||||
// num_fields and the types of the LogVals must match what was passed
|
||||
// to Init().
|
||||
//
|
||||
// Returns false if an error occured, in which case the writer must
|
||||
// not be used any further.
|
||||
bool Write(int num_fields, LogVal** vals);
|
||||
|
||||
// Sets the buffering status for the writer, if the writer supports
|
||||
// that. (If not, it will be ignored).
|
||||
bool SetBuf(bool enabled);
|
||||
|
||||
// Flushes any currently buffered output, if the writer supports
|
||||
// that. (If not, it will be ignored).
|
||||
bool Flush();
|
||||
|
||||
// Triggers rotation, if the writer supports that. (If not, it will
|
||||
// be ignored).
|
||||
bool Rotate(string rotated_path, double open, double close, bool terminating);
|
||||
|
||||
// Finishes writing to this logger regularly. Must not be called if
|
||||
// an error has been indicated earlier. After calling this, no
|
||||
// further writing must be performed.
|
||||
void Finish();
|
||||
|
||||
//// Thread-safe methods that may be called from the writer
|
||||
//// implementation.
|
||||
|
||||
// The following methods return the information as passed to Init().
|
||||
const string Path() const { return path; }
|
||||
int NumFields() const { return num_fields; }
|
||||
const LogField* const * Fields() const { return fields; }
|
||||
|
||||
protected:
|
||||
// Methods for writers to override. If any of these returs false, it
|
||||
// will be assumed that a fatal error has occured that prevents the
|
||||
// writer from further operation. It will then be disabled and
|
||||
// deleted. When return false, the writer should also report the
|
||||
// error via Error(). Note that even if a writer does not support the
|
||||
// functionality for one these methods (like rotation), it must still
|
||||
// return true if that is not to be considered a fatal error.
|
||||
//
|
||||
// Called once for initialization of the writer.
|
||||
virtual bool DoInit(string path, int num_fields,
|
||||
const LogField* const * fields) = 0;
|
||||
|
||||
// Called once per log entry to record.
|
||||
virtual bool DoWrite(int num_fields, const LogField* const * fields,
|
||||
LogVal** vals) = 0;
|
||||
|
||||
// Called when the buffering status for this writer is changed. If
|
||||
// buffering is disabled, the writer should attempt to write out
|
||||
// information as quickly as possible even if doing so may have a
|
||||
// performance impact. If enabled (which is the default), it may
|
||||
// buffer data as helpful and write it out later in a way optimized
|
||||
// for performance. The current buffering state can be queried via
|
||||
// IsBuf().
|
||||
//
|
||||
// A writer may ignore buffering changes if it doesn't fit with its
|
||||
// semantics (but must still return true in that case).
|
||||
virtual bool DoSetBuf(bool enabled) = 0;
|
||||
|
||||
// Called to flush any currently buffered output.
|
||||
//
|
||||
// A writer may ignore flush requests if it doesn't fit with its
|
||||
// semantics (but must still return true in that case).
|
||||
virtual bool DoFlush() = 0;
|
||||
|
||||
// Called when a log output is to be rotated. Most directly this only
|
||||
// applies to writers writing into files, which should then close the
|
||||
// current file and open a new one. However, a writer may also
|
||||
// trigger other apppropiate actions if semantics are similar.
|
||||
//
|
||||
// Once rotation has finished, the implementation should call
|
||||
// RotationDone() to signal the log manager that potential
|
||||
// postprocessors can now run.
|
||||
//
|
||||
// "rotate_path" reflects the path to where the rotated output is to
|
||||
// be moved, with specifics depending on the writer. It should
|
||||
// generally be interpreted in a way consistent with that of "path"
|
||||
// as passed into DoInit(). As an example, for file-based output,
|
||||
// "rotate_path" could be the original filename extended with a
|
||||
// timestamp indicating the time of the rotation.
|
||||
//
|
||||
// "open" and "close" are the network time's when the *current* file
|
||||
// was opened and closed, respectively.
|
||||
//
|
||||
// "terminating" indicated whether the rotation request occurs due
|
||||
// the main Bro prcoess terminating (and not because we've reach a
|
||||
// regularly scheduled time for rotation).
|
||||
//
|
||||
// A writer may ignore rotation requests if it doesn't fit with its
|
||||
// semantics (but must still return true in that case).
|
||||
virtual bool DoRotate(string rotated_path, double open, double close,
|
||||
bool terminating) = 0;
|
||||
|
||||
// Called once on termination. Not called when any of the other
|
||||
// methods has previously signaled an error, i.e., executing this
|
||||
// method signals a regular shutdown of the writer.
|
||||
virtual void DoFinish() = 0;
|
||||
|
||||
//// Methods for writers to use. These are thread-safe.
|
||||
|
||||
// A thread-safe version of fmt().
|
||||
const char* Fmt(const char* format, ...);
|
||||
|
||||
// Returns the current buffering state.
|
||||
bool IsBuf() { return buffering; }
|
||||
|
||||
// Reports an error to the user.
|
||||
void Error(const char *msg);
|
||||
|
||||
// Signals to the log manager that a file has been rotated.
|
||||
//
|
||||
// new_name: The filename of the rotated file. old_name: The filename
|
||||
// of the origina file.
|
||||
//
|
||||
// open/close: The timestamps when the original file was opened and
|
||||
// closed, respectively.
|
||||
//
|
||||
// terminating: True if rotation request occured due to the main Bro
|
||||
// process shutting down.
|
||||
bool FinishedRotation(string new_name, string old_name, double open,
|
||||
double close, bool terminating);
|
||||
|
||||
private:
|
||||
friend class LogMgr;
|
||||
|
||||
// When an error occurs, we call this method to set a flag marking
|
||||
// the writer as disabled. The LogMgr will check the flag later and
|
||||
// remove the writer.
|
||||
bool Disabled() { return disabled; }
|
||||
|
||||
// Deletes the values as passed into Write().
|
||||
void DeleteVals(LogVal** vals);
|
||||
|
||||
string path;
|
||||
int num_fields;
|
||||
const LogField* const * fields;
|
||||
bool buffering;
|
||||
bool disabled;
|
||||
|
||||
// For implementing Fmt().
|
||||
char* buf;
|
||||
unsigned int buf_len;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,30 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
//
|
||||
// Dummy log writer that just discards everything (but still pretends to rotate).
|
||||
|
||||
#ifndef LOGWRITERNONE_H
|
||||
#define LOGWRITERNONE_H
|
||||
|
||||
#include "LogWriter.h"
|
||||
|
||||
class LogWriterNone : public LogWriter {
|
||||
public:
|
||||
LogWriterNone() {}
|
||||
~LogWriterNone() {};
|
||||
|
||||
static LogWriter* Instantiate() { return new LogWriterNone; }
|
||||
|
||||
protected:
|
||||
virtual bool DoInit(string path, int num_fields,
|
||||
const LogField* const * fields) { return true; }
|
||||
|
||||
virtual bool DoWrite(int num_fields, const LogField* const * fields,
|
||||
LogVal** vals) { return true; }
|
||||
virtual bool DoSetBuf(bool enabled) { return true; }
|
||||
virtual bool DoRotate(string rotated_path, double open, double close,
|
||||
bool terminating);
|
||||
virtual bool DoFlush() { return true; }
|
||||
virtual void DoFinish() {}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -38,7 +38,7 @@ Login_Analyzer::Login_Analyzer(AnalyzerTag::Tag tag, Connection* conn)
|
|||
|
||||
if ( ! re_skip_authentication )
|
||||
{
|
||||
#ifdef USE_PERFTOOLS
|
||||
#ifdef USE_PERFTOOLS_DEBUG
|
||||
HeapLeakChecker::Disabler disabler;
|
||||
#endif
|
||||
re_skip_authentication = init_RE(skip_authentication);
|
||||
|
|
|
@ -225,5 +225,7 @@ NCP_Analyzer::NCP_Analyzer(Connection* conn)
|
|||
NCP_Analyzer::~NCP_Analyzer()
|
||||
{
|
||||
delete session;
|
||||
delete o_ncp;
|
||||
delete r_ncp;
|
||||
}
|
||||
|
||||
|
|
12
src/Net.cc
12
src/Net.cc
|
@ -42,7 +42,6 @@ extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
|
|||
PList(PktSrc) pkt_srcs;
|
||||
|
||||
// FIXME: We should really merge PktDumper and PacketDumper.
|
||||
// It's on my to-do [Robin].
|
||||
PktDumper* pkt_dumper = 0;
|
||||
|
||||
int reading_live = 0;
|
||||
|
@ -248,12 +247,14 @@ void net_init(name_list& interfaces, name_list& readfiles,
|
|||
FlowSocketSrc* fs = new FlowSocketSrc(netflows[i]);
|
||||
|
||||
if ( ! fs->IsOpen() )
|
||||
{
|
||||
reporter->Error("%s: problem with netflow socket %s - %s\n",
|
||||
prog, netflows[i], fs->ErrorMsg());
|
||||
else
|
||||
{
|
||||
io_sources.Register(fs);
|
||||
delete fs;
|
||||
}
|
||||
|
||||
else
|
||||
io_sources.Register(fs);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -454,6 +455,7 @@ void net_run()
|
|||
// date on timers and events.
|
||||
network_time = ct;
|
||||
expire_timers();
|
||||
usleep(1); // Just yield.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -483,6 +485,8 @@ void net_run()
|
|||
// since Bro timers are not high-precision anyway.)
|
||||
if ( ! using_communication )
|
||||
usleep(100000);
|
||||
else
|
||||
usleep(1000);
|
||||
|
||||
// Flawfinder says about usleep:
|
||||
//
|
||||
|
|
|
@ -47,15 +47,6 @@ int tcp_max_initial_window;
|
|||
int tcp_max_above_hole_without_any_acks;
|
||||
int tcp_excessive_data_without_further_acks;
|
||||
|
||||
int ssl_compare_cipherspecs;
|
||||
int ssl_analyze_certificates;
|
||||
int ssl_store_certificates;
|
||||
int ssl_verify_certificates;
|
||||
int ssl_store_key_material;
|
||||
int ssl_max_cipherspec_size;
|
||||
StringVal* ssl_store_cert_path;
|
||||
StringVal* x509_trusted_cert_path;
|
||||
TableType* cipher_suites_list;
|
||||
RecordType* x509_type;
|
||||
|
||||
double non_analyzed_lifetime;
|
||||
|
@ -192,8 +183,6 @@ StringVal* ssl_ca_certificate;
|
|||
StringVal* ssl_private_key;
|
||||
StringVal* ssl_passphrase;
|
||||
|
||||
StringVal* x509_crl_file;
|
||||
|
||||
Val* profiling_file;
|
||||
double profiling_interval;
|
||||
int expensive_profiling_multiple;
|
||||
|
@ -213,11 +202,6 @@ int sig_max_group_size;
|
|||
|
||||
int enable_syslog;
|
||||
|
||||
int use_connection_compressor;
|
||||
int cc_handle_resets;
|
||||
int cc_handle_only_syns;
|
||||
int cc_instantiate_on_data;
|
||||
|
||||
TableType* irc_join_list;
|
||||
RecordType* irc_join_info;
|
||||
TableVal* irc_servers;
|
||||
|
@ -358,17 +342,7 @@ void init_net_var()
|
|||
tcp_excessive_data_without_further_acks =
|
||||
opt_internal_int("tcp_excessive_data_without_further_acks");
|
||||
|
||||
ssl_compare_cipherspecs = opt_internal_int("ssl_compare_cipherspecs");
|
||||
ssl_analyze_certificates = opt_internal_int("ssl_analyze_certificates");
|
||||
ssl_store_certificates = opt_internal_int("ssl_store_certificates");
|
||||
ssl_verify_certificates = opt_internal_int("ssl_verify_certificates");
|
||||
ssl_store_key_material = opt_internal_int("ssl_store_key_material");
|
||||
ssl_max_cipherspec_size = opt_internal_int("ssl_max_cipherspec_size");
|
||||
|
||||
x509_trusted_cert_path = opt_internal_string("X509_trusted_cert_path");
|
||||
ssl_store_cert_path = opt_internal_string("ssl_store_cert_path");
|
||||
x509_type = internal_type("X509")->AsRecordType();
|
||||
x509_crl_file = opt_internal_string("X509_crl_file");
|
||||
|
||||
non_analyzed_lifetime = opt_internal_double("non_analyzed_lifetime");
|
||||
tcp_inactivity_timeout = opt_internal_double("tcp_inactivity_timeout");
|
||||
|
@ -525,12 +499,6 @@ void init_net_var()
|
|||
|
||||
gap_report_freq = opt_internal_double("gap_report_freq");
|
||||
|
||||
use_connection_compressor =
|
||||
opt_internal_int("use_connection_compressor");
|
||||
cc_handle_resets = opt_internal_int("cc_handle_resets");
|
||||
cc_handle_only_syns = opt_internal_int("cc_handle_only_syns");
|
||||
cc_instantiate_on_data = opt_internal_int("cc_instantiate_on_data");
|
||||
|
||||
irc_join_info = internal_type("irc_join_info")->AsRecordType();
|
||||
irc_join_list = internal_type("irc_join_list")->AsTableType();
|
||||
irc_servers = internal_val("irc_servers")->AsTableVal();
|
||||
|
|
15
src/NetVar.h
15
src/NetVar.h
|
@ -50,17 +50,7 @@ extern int tcp_max_initial_window;
|
|||
extern int tcp_max_above_hole_without_any_acks;
|
||||
extern int tcp_excessive_data_without_further_acks;
|
||||
|
||||
// see policy/ssl.bro for details
|
||||
extern int ssl_compare_cipherspecs;
|
||||
extern int ssl_analyze_certificates;
|
||||
extern int ssl_store_certificates;
|
||||
extern int ssl_verify_certificates;
|
||||
extern int ssl_store_key_material;
|
||||
extern int ssl_max_cipherspec_size;
|
||||
extern StringVal* ssl_store_cert_path;
|
||||
extern StringVal* x509_trusted_cert_path;
|
||||
extern RecordType* x509_type;
|
||||
extern StringVal* x509_crl_file;
|
||||
|
||||
extern double non_analyzed_lifetime;
|
||||
extern double tcp_inactivity_timeout;
|
||||
|
@ -216,11 +206,6 @@ extern int sig_max_group_size;
|
|||
|
||||
extern int enable_syslog;
|
||||
|
||||
extern int use_connection_compressor;
|
||||
extern int cc_handle_resets;
|
||||
extern int cc_handle_only_syns;
|
||||
extern int cc_instantiate_on_data;
|
||||
|
||||
extern TableType* irc_join_list;
|
||||
extern RecordType* irc_join_info;
|
||||
extern TableVal* irc_servers;
|
||||
|
|
|
@ -131,6 +131,9 @@ int NetbiosSSN_Interpreter::ParseBroadcast(const u_char* data, int len,
|
|||
return 0;
|
||||
}
|
||||
|
||||
delete srcname;
|
||||
delete dstname;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,15 +63,16 @@ OSFingerprint::OSFingerprint(FingerprintMode arg_mode)
|
|||
}
|
||||
}
|
||||
|
||||
bool OSFingerprint::CacheMatch(uint32 addr, int id)
|
||||
bool OSFingerprint::CacheMatch(const IPAddr& addr, int id)
|
||||
{
|
||||
HashKey key = HashKey(&addr, 1);
|
||||
HashKey* key = addr.GetHashKey();
|
||||
int* pid = new int;
|
||||
*pid=id;
|
||||
int* prev = os_matches.Insert(&key, pid);
|
||||
int* prev = os_matches.Insert(key, pid);
|
||||
bool ret = (prev ? *prev != id : 1);
|
||||
if (prev)
|
||||
delete prev;
|
||||
delete key;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "util.h"
|
||||
#include "Dict.h"
|
||||
#include "Reporter.h"
|
||||
#include "IPAddr.h"
|
||||
|
||||
// Size limit for size wildcards.
|
||||
#define PACKET_BIG 100
|
||||
|
@ -88,7 +89,7 @@ public:
|
|||
int FindMatch(struct os_type* retval, uint16 tot, uint8 DF_flag,
|
||||
uint8 TTL, uint16 WSS, uint8 ocnt, uint8* op, uint16 MSS,
|
||||
uint8 win_scale, uint32 tstamp, uint32 quirks, uint8 ECN) const;
|
||||
bool CacheMatch(uint32 addr, int id);
|
||||
bool CacheMatch(const IPAddr& addr, int id);
|
||||
|
||||
int Get_OS_From_SYN(struct os_type* retval,
|
||||
uint16 tot, uint8 DF_flag, uint8 TTL, uint16 WSS,
|
||||
|
|
10
src/PIA.cc
10
src/PIA.cc
|
@ -196,20 +196,20 @@ void PIA_TCP::FirstPacket(bool is_orig, const IP_Hdr* ip)
|
|||
ip4->ip_p = IPPROTO_TCP;
|
||||
|
||||
// Cast to const so that it doesn't delete it.
|
||||
ip4_hdr = new IP_Hdr((const struct ip*) ip4);
|
||||
ip4_hdr = new IP_Hdr(ip4, false);
|
||||
}
|
||||
|
||||
if ( is_orig )
|
||||
{
|
||||
copy_addr(Conn()->OrigAddr(), &ip4->ip_src.s_addr);
|
||||
copy_addr(Conn()->RespAddr(), &ip4->ip_dst.s_addr);
|
||||
Conn()->OrigAddr().CopyIPv4(&ip4->ip_src);
|
||||
Conn()->RespAddr().CopyIPv4(&ip4->ip_dst);
|
||||
tcp4->th_sport = htons(Conn()->OrigPort());
|
||||
tcp4->th_dport = htons(Conn()->RespPort());
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_addr(Conn()->RespAddr(), &ip4->ip_src.s_addr);
|
||||
copy_addr(Conn()->OrigAddr(), &ip4->ip_dst.s_addr);
|
||||
Conn()->RespAddr().CopyIPv4(&ip4->ip_src);
|
||||
Conn()->OrigAddr().CopyIPv4(&ip4->ip_dst);
|
||||
tcp4->th_sport = htons(Conn()->RespPort());
|
||||
tcp4->th_dport = htons(Conn()->OrigPort());
|
||||
}
|
||||
|
|
|
@ -158,6 +158,7 @@ void POP3_Analyzer::ProcessRequest(int length, const char* line)
|
|||
if ( e >= end )
|
||||
{
|
||||
Weird("pop3_malformed_auth_plain");
|
||||
delete decoded;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -167,6 +168,7 @@ void POP3_Analyzer::ProcessRequest(int length, const char* line)
|
|||
if ( s >= end )
|
||||
{
|
||||
Weird("pop3_malformed_auth_plain");
|
||||
delete decoded;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "PacketFilter.h"
|
||||
|
||||
void PacketFilter::AddSrc(addr_type src, uint32 tcp_flags, double probability)
|
||||
void PacketFilter::AddSrc(const IPAddr& src, uint32 tcp_flags, double probability)
|
||||
{
|
||||
Filter* f = new Filter;
|
||||
f->tcp_flags = tcp_flags;
|
||||
f->probability = uint32(probability * RAND_MAX);
|
||||
src_filter.Insert(src, NUM_ADDR_WORDS * 32, f);
|
||||
src_filter.Insert(src, 128, f);
|
||||
}
|
||||
|
||||
void PacketFilter::AddSrc(Val* src, uint32 tcp_flags, double probability)
|
||||
|
@ -16,12 +16,12 @@ void PacketFilter::AddSrc(Val* src, uint32 tcp_flags, double probability)
|
|||
src_filter.Insert(src, f);
|
||||
}
|
||||
|
||||
void PacketFilter::AddDst(addr_type dst, uint32 tcp_flags, double probability)
|
||||
void PacketFilter::AddDst(const IPAddr& dst, uint32 tcp_flags, double probability)
|
||||
{
|
||||
Filter* f = new Filter;
|
||||
f->tcp_flags = tcp_flags;
|
||||
f->probability = uint32(probability * RAND_MAX);
|
||||
dst_filter.Insert(dst, NUM_ADDR_WORDS * 32, f);
|
||||
dst_filter.Insert(dst, 128, f);
|
||||
}
|
||||
|
||||
void PacketFilter::AddDst(Val* dst, uint32 tcp_flags, double probability)
|
||||
|
@ -32,9 +32,9 @@ void PacketFilter::AddDst(Val* dst, uint32 tcp_flags, double probability)
|
|||
dst_filter.Insert(dst, f);
|
||||
}
|
||||
|
||||
bool PacketFilter::RemoveSrc(addr_type src)
|
||||
bool PacketFilter::RemoveSrc(const IPAddr& src)
|
||||
{
|
||||
return src_filter.Remove(src, NUM_ADDR_WORDS * 32) != 0;
|
||||
return src_filter.Remove(src, 128) != 0;
|
||||
}
|
||||
|
||||
bool PacketFilter::RemoveSrc(Val* src)
|
||||
|
@ -42,9 +42,9 @@ bool PacketFilter::RemoveSrc(Val* src)
|
|||
return src_filter.Remove(src) != NULL;
|
||||
}
|
||||
|
||||
bool PacketFilter::RemoveDst(addr_type dst)
|
||||
bool PacketFilter::RemoveDst(const IPAddr& dst)
|
||||
{
|
||||
return dst_filter.Remove(dst, NUM_ADDR_WORDS * 32) != NULL;
|
||||
return dst_filter.Remove(dst, 128) != NULL;
|
||||
}
|
||||
|
||||
bool PacketFilter::RemoveDst(Val* dst)
|
||||
|
@ -54,21 +54,11 @@ bool PacketFilter::RemoveDst(Val* dst)
|
|||
|
||||
bool PacketFilter::Match(const IP_Hdr* ip, int len, int caplen)
|
||||
{
|
||||
#ifdef BROv6
|
||||
Filter* f = (Filter*) src_filter.Lookup(ip->SrcAddr(),
|
||||
NUM_ADDR_WORDS * 32);
|
||||
#else
|
||||
Filter* f = (Filter*) src_filter.Lookup(*ip->SrcAddr(),
|
||||
NUM_ADDR_WORDS * 32);
|
||||
#endif
|
||||
Filter* f = (Filter*) src_filter.Lookup(ip->SrcAddr(), 128);
|
||||
if ( f )
|
||||
return MatchFilter(*f, *ip, len, caplen);
|
||||
|
||||
#ifdef BROv6
|
||||
f = (Filter*) dst_filter.Lookup(ip->DstAddr(), NUM_ADDR_WORDS * 32);
|
||||
#else
|
||||
f = (Filter*) dst_filter.Lookup(*ip->DstAddr(), NUM_ADDR_WORDS * 32);
|
||||
#endif
|
||||
f = (Filter*) dst_filter.Lookup(ip->DstAddr(), 128);
|
||||
if ( f )
|
||||
return MatchFilter(*f, *ip, len, caplen);
|
||||
|
||||
|
@ -81,9 +71,7 @@ bool PacketFilter::MatchFilter(const Filter& f, const IP_Hdr& ip,
|
|||
if ( ip.NextProto() == IPPROTO_TCP && f.tcp_flags )
|
||||
{
|
||||
// Caution! The packet sanity checks have not been performed yet
|
||||
const struct ip* ip4 = ip.IP4_Hdr();
|
||||
|
||||
int ip_hdr_len = ip4->ip_hl * 4;
|
||||
int ip_hdr_len = ip.HdrLen();
|
||||
len -= ip_hdr_len; // remove IP header
|
||||
caplen -= ip_hdr_len;
|
||||
|
||||
|
@ -92,8 +80,7 @@ bool PacketFilter::MatchFilter(const Filter& f, const IP_Hdr& ip,
|
|||
// Packet too short, will be dropped anyway.
|
||||
return false;
|
||||
|
||||
const struct tcphdr* tp =
|
||||
(const struct tcphdr*) ((u_char*) ip4 + ip_hdr_len);
|
||||
const struct tcphdr* tp = (const struct tcphdr*) ip.Payload();
|
||||
|
||||
if ( tp->th_flags & f.tcp_flags )
|
||||
// At least one of the flags is set, so don't drop
|
||||
|
|
|
@ -14,16 +14,16 @@ public:
|
|||
// Drops all packets from a particular source (which may be given
|
||||
// as an AddrVal or a SubnetVal) which hasn't any of TCP flags set
|
||||
// (TH_*) with the given probability (from 0..MAX_PROB).
|
||||
void AddSrc(addr_type src, uint32 tcp_flags, double probability);
|
||||
void AddSrc(const IPAddr& src, uint32 tcp_flags, double probability);
|
||||
void AddSrc(Val* src, uint32 tcp_flags, double probability);
|
||||
void AddDst(addr_type src, uint32 tcp_flags, double probability);
|
||||
void AddDst(const IPAddr& src, uint32 tcp_flags, double probability);
|
||||
void AddDst(Val* src, uint32 tcp_flags, double probability);
|
||||
|
||||
// Removes the filter entry for the given src/dst
|
||||
// Returns false if filter doesn not exist.
|
||||
bool RemoveSrc(addr_type src);
|
||||
bool RemoveSrc(const IPAddr& src);
|
||||
bool RemoveSrc(Val* dst);
|
||||
bool RemoveDst(addr_type dst);
|
||||
bool RemoveDst(const IPAddr& dst);
|
||||
bool RemoveDst(Val* dst);
|
||||
|
||||
// Returns true if packet matches a drop filter
|
||||
|
|
|
@ -27,13 +27,16 @@ PacketSortElement::PacketSortElement(PktSrc* arg_src,
|
|||
{
|
||||
const struct ip* ip = (const struct ip*) (pkt + hdr_size);
|
||||
if ( ip->ip_v == 4 )
|
||||
ip_hdr = new IP_Hdr(ip);
|
||||
ip_hdr = new IP_Hdr(ip, false);
|
||||
else if ( ip->ip_v == 6 && (caplen >= sizeof(struct ip6_hdr) + hdr_size) )
|
||||
ip_hdr = new IP_Hdr((const struct ip6_hdr*) ip, false, caplen - hdr_size);
|
||||
else
|
||||
ip_hdr = new IP_Hdr((const struct ip6_hdr*) ip);
|
||||
// Weird will be generated later in NetSessions::NextPacket.
|
||||
return;
|
||||
|
||||
if ( ip_hdr->NextProto() == IPPROTO_TCP &&
|
||||
// Note: can't sort fragmented packets
|
||||
(ip_hdr->FragField() & 0x3fff) == 0 )
|
||||
( ! ip_hdr->IsFragment() ) )
|
||||
{
|
||||
tcp_offset = hdr_size + ip_hdr->HdrLen();
|
||||
if ( caplen >= tcp_offset + sizeof(struct tcphdr) )
|
||||
|
@ -65,7 +68,7 @@ PacketSortElement::PacketSortElement(PktSrc* arg_src,
|
|||
|
||||
payload_length = ip_hdr->PayloadLen() - tp->th_off * 4;
|
||||
|
||||
key = id.BuildConnKey();
|
||||
key = BuildConnIDHashKey(id);
|
||||
|
||||
is_tcp = 1;
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ bool PersistenceSerializer::CheckForFile(UnserialInfo* info, const char* file,
|
|||
|
||||
bool PersistenceSerializer::ReadAll(bool is_init, bool delete_files)
|
||||
{
|
||||
#ifdef USE_PERFTOOLS
|
||||
#ifdef USE_PERFTOOLS_DEBUG
|
||||
HeapLeakChecker::Disabler disabler;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -382,6 +382,7 @@ void PktSrc::AddSecondaryTablePrograms()
|
|||
{
|
||||
delete program;
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
SecondaryProgram* sp = new SecondaryProgram(program, se);
|
||||
|
|
|
@ -1,34 +1,19 @@
|
|||
#include "PrefixTable.h"
|
||||
#include "Reporter.h"
|
||||
|
||||
// IPv4 version.
|
||||
inline static prefix_t* make_prefix(const uint32 addr, int width)
|
||||
inline static prefix_t* make_prefix(const IPAddr& addr, int width)
|
||||
{
|
||||
prefix_t* prefix = (prefix_t*) safe_malloc(sizeof(prefix_t));
|
||||
|
||||
memcpy(&prefix->add.sin, &addr, sizeof(prefix->add.sin)) ;
|
||||
prefix->family = AF_INET;
|
||||
prefix->bitlen = width;
|
||||
prefix->ref_count = 1;
|
||||
|
||||
return prefix;
|
||||
}
|
||||
|
||||
#ifdef BROv6
|
||||
inline static prefix_t* make_prefix(const uint32* addr, int width)
|
||||
{
|
||||
prefix_t* prefix = (prefix_t*) safe_malloc(sizeof(prefix_t));
|
||||
|
||||
memcpy(&prefix->add.sin6, addr, 4 * sizeof(uint32));
|
||||
addr.CopyIPv6(&prefix->add.sin6);
|
||||
prefix->family = AF_INET6;
|
||||
prefix->bitlen = width;
|
||||
prefix->ref_count = 1;
|
||||
|
||||
return prefix;
|
||||
}
|
||||
#endif
|
||||
|
||||
void* PrefixTable::Insert(const_addr_type addr, int width, void* data)
|
||||
void* PrefixTable::Insert(const IPAddr& addr, int width, void* data)
|
||||
{
|
||||
prefix_t* prefix = make_prefix(addr, width);
|
||||
patricia_node_t* node = patricia_lookup(tree, prefix);
|
||||
|
@ -55,12 +40,12 @@ void* PrefixTable::Insert(const Val* value, void* data)
|
|||
|
||||
switch ( value->Type()->Tag() ) {
|
||||
case TYPE_ADDR:
|
||||
return Insert(value->AsAddr(), NUM_ADDR_WORDS * 32, data);
|
||||
return Insert(value->AsAddr(), 128, data);
|
||||
break;
|
||||
|
||||
case TYPE_SUBNET:
|
||||
return Insert(value->AsSubNet()->net,
|
||||
value->AsSubNet()->width, data);
|
||||
return Insert(value->AsSubNet().Prefix(),
|
||||
value->AsSubNet().LengthIPv6(), data);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -69,7 +54,7 @@ void* PrefixTable::Insert(const Val* value, void* data)
|
|||
}
|
||||
}
|
||||
|
||||
void* PrefixTable::Lookup(const_addr_type addr, int width, bool exact) const
|
||||
void* PrefixTable::Lookup(const IPAddr& addr, int width, bool exact) const
|
||||
{
|
||||
prefix_t* prefix = make_prefix(addr, width);
|
||||
patricia_node_t* node =
|
||||
|
@ -89,12 +74,12 @@ void* PrefixTable::Lookup(const Val* value, bool exact) const
|
|||
|
||||
switch ( value->Type()->Tag() ) {
|
||||
case TYPE_ADDR:
|
||||
return Lookup(value->AsAddr(), NUM_ADDR_WORDS * 32, exact);
|
||||
return Lookup(value->AsAddr(), 128, exact);
|
||||
break;
|
||||
|
||||
case TYPE_SUBNET:
|
||||
return Lookup(value->AsSubNet()->net,
|
||||
value->AsSubNet()->width, exact);
|
||||
return Lookup(value->AsSubNet().Prefix(),
|
||||
value->AsSubNet().LengthIPv6(), exact);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -104,7 +89,7 @@ void* PrefixTable::Lookup(const Val* value, bool exact) const
|
|||
}
|
||||
}
|
||||
|
||||
void* PrefixTable::Remove(const_addr_type addr, int width)
|
||||
void* PrefixTable::Remove(const IPAddr& addr, int width)
|
||||
{
|
||||
prefix_t* prefix = make_prefix(addr, width);
|
||||
patricia_node_t* node = patricia_search_exact(tree, prefix);
|
||||
|
@ -128,11 +113,12 @@ void* PrefixTable::Remove(const Val* value)
|
|||
|
||||
switch ( value->Type()->Tag() ) {
|
||||
case TYPE_ADDR:
|
||||
return Remove(value->AsAddr(), NUM_ADDR_WORDS * 32);
|
||||
return Remove(value->AsAddr(), 128);
|
||||
break;
|
||||
|
||||
case TYPE_SUBNET:
|
||||
return Remove(value->AsSubNet()->net, value->AsSubNet()->width);
|
||||
return Remove(value->AsSubNet().Prefix(),
|
||||
value->AsSubNet().LengthIPv6());
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "Val.h"
|
||||
#include "net_util.h"
|
||||
#include "IPAddr.h"
|
||||
|
||||
extern "C" {
|
||||
#include "patricia.h"
|
||||
|
@ -24,7 +25,7 @@ public:
|
|||
// Addr in network byte order. If data is zero, acts like a set.
|
||||
// Returns ptr to old data if already existing.
|
||||
// For existing items without data, returns non-nil if found.
|
||||
void* Insert(const_addr_type addr, int width, void* data = 0);
|
||||
void* Insert(const IPAddr& addr, int width, void* data = 0);
|
||||
|
||||
// Value may be addr or subnet.
|
||||
void* Insert(const Val* value, void* data = 0);
|
||||
|
@ -32,11 +33,11 @@ public:
|
|||
// Returns nil if not found, pointer to data otherwise.
|
||||
// For items without data, returns non-nil if found.
|
||||
// If exact is false, performs exact rather than longest-prefix match.
|
||||
void* Lookup(const_addr_type addr, int width, bool exact = false) const;
|
||||
void* Lookup(const IPAddr& addr, int width, bool exact = false) const;
|
||||
void* Lookup(const Val* value, bool exact = false) const;
|
||||
|
||||
// Returns pointer to data or nil if not found.
|
||||
void* Remove(const_addr_type addr, int width);
|
||||
void* Remove(const IPAddr& addr, int width);
|
||||
void* Remove(const Val* value);
|
||||
|
||||
void Clear() { Clear_Patricia(tree, 0); }
|
||||
|
|
|
@ -43,8 +43,7 @@ DataBlock::DataBlock(const u_char* data, int size, int arg_seq,
|
|||
|
||||
unsigned int Reassembler::total_size = 0;
|
||||
|
||||
Reassembler::Reassembler(int init_seq, const uint32* ip_addr,
|
||||
ReassemblerType arg_type)
|
||||
Reassembler::Reassembler(int init_seq, ReassemblerType arg_type)
|
||||
{
|
||||
blocks = last_block = 0;
|
||||
trim_seq = last_reassem_seq = init_seq;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#define reassem_h
|
||||
|
||||
#include "Obj.h"
|
||||
#include "IPAddr.h"
|
||||
|
||||
class DataBlock {
|
||||
public:
|
||||
|
@ -25,8 +26,7 @@ enum ReassemblerType { REASSEM_IP, REASSEM_TCP };
|
|||
|
||||
class Reassembler : public BroObj {
|
||||
public:
|
||||
Reassembler(int init_seq, const uint32* ip_addr,
|
||||
ReassemblerType arg_type);
|
||||
Reassembler(int init_seq, ReassemblerType arg_type);
|
||||
virtual ~Reassembler();
|
||||
|
||||
void NewBlock(double t, int seq, int len, const u_char* data);
|
||||
|
|
|
@ -183,8 +183,11 @@
|
|||
#include "Sessions.h"
|
||||
#include "File.h"
|
||||
#include "Conn.h"
|
||||
#include "LogMgr.h"
|
||||
#include "Reporter.h"
|
||||
#include "threading/SerialTypes.h"
|
||||
#include "logging/Manager.h"
|
||||
#include "IPAddr.h"
|
||||
#include "bro_inet_ntop.h"
|
||||
|
||||
extern "C" {
|
||||
#include "setsignal.h"
|
||||
|
@ -463,7 +466,7 @@ static inline const char* ip2a(uint32 ip)
|
|||
|
||||
addr.s_addr = htonl(ip);
|
||||
|
||||
return inet_ntop(AF_INET, &addr, buffer, 32);
|
||||
return bro_inet_ntop(AF_INET, &addr, buffer, 32);
|
||||
}
|
||||
|
||||
static pid_t child_pid = 0;
|
||||
|
@ -530,6 +533,7 @@ RemoteSerializer::RemoteSerializer()
|
|||
terminating = false;
|
||||
in_sync = 0;
|
||||
last_flush = 0;
|
||||
received_logs = 0;
|
||||
}
|
||||
|
||||
RemoteSerializer::~RemoteSerializer()
|
||||
|
@ -670,8 +674,8 @@ void RemoteSerializer::Fork()
|
|||
}
|
||||
}
|
||||
|
||||
RemoteSerializer::PeerID RemoteSerializer::Connect(addr_type ip, uint16 port,
|
||||
const char* our_class, double retry, bool use_ssl)
|
||||
RemoteSerializer::PeerID RemoteSerializer::Connect(const IPAddr& ip,
|
||||
uint16 port, const char* our_class, double retry, bool use_ssl)
|
||||
{
|
||||
if ( ! using_communication )
|
||||
return true;
|
||||
|
@ -679,16 +683,12 @@ RemoteSerializer::PeerID RemoteSerializer::Connect(addr_type ip, uint16 port,
|
|||
if ( ! initialized )
|
||||
reporter->InternalError("remote serializer not initialized");
|
||||
|
||||
#ifdef BROv6
|
||||
if ( ! is_v4_addr(ip) )
|
||||
if ( ip.GetFamily() == IPv6 )
|
||||
Error("inter-Bro communication not supported over IPv6");
|
||||
|
||||
uint32 ip4 = to_v4_addr(ip);
|
||||
#else
|
||||
uint32 ip4 = ip;
|
||||
#endif
|
||||
|
||||
ip4 = ntohl(ip4);
|
||||
const uint32* bytes;
|
||||
ip.GetBytes(&bytes);
|
||||
uint32 ip4 = ntohl(*bytes);
|
||||
|
||||
if ( ! child_pid )
|
||||
Fork();
|
||||
|
@ -1232,7 +1232,7 @@ bool RemoteSerializer::SendCapabilities(Peer* peer)
|
|||
return caps ? SendToChild(MSG_CAPS, peer, 3, caps, 0, 0) : true;
|
||||
}
|
||||
|
||||
bool RemoteSerializer::Listen(addr_type ip, uint16 port, bool expect_ssl)
|
||||
bool RemoteSerializer::Listen(const IPAddr& ip, uint16 port, bool expect_ssl)
|
||||
{
|
||||
if ( ! using_communication )
|
||||
return true;
|
||||
|
@ -1240,16 +1240,12 @@ bool RemoteSerializer::Listen(addr_type ip, uint16 port, bool expect_ssl)
|
|||
if ( ! initialized )
|
||||
reporter->InternalError("remote serializer not initialized");
|
||||
|
||||
#ifdef BROv6
|
||||
if ( ! is_v4_addr(ip) )
|
||||
if ( ip.GetFamily() == IPv6 )
|
||||
Error("inter-Bro communication not supported over IPv6");
|
||||
|
||||
uint32 ip4 = to_v4_addr(ip);
|
||||
#else
|
||||
uint32 ip4 = ip;
|
||||
#endif
|
||||
|
||||
ip4 = ntohl(ip4);
|
||||
const uint32* bytes;
|
||||
ip.GetBytes(&bytes);
|
||||
uint32 ip4 = ntohl(*bytes);
|
||||
|
||||
if ( ! SendToChild(MSG_LISTEN, 0, 3, ip4, port, expect_ssl) )
|
||||
return false;
|
||||
|
@ -1359,6 +1355,14 @@ double RemoteSerializer::NextTimestamp(double* local_network_time)
|
|||
{
|
||||
Poll(false);
|
||||
|
||||
if ( received_logs > 0 )
|
||||
{
|
||||
// If we processed logs last time, assume there's more.
|
||||
idle = false;
|
||||
received_logs = 0;
|
||||
return timer_mgr->Time();
|
||||
}
|
||||
|
||||
double et = events.length() ? events[0]->time : -1;
|
||||
double pt = packets.length() ? packets[0]->time : -1;
|
||||
|
||||
|
@ -2476,7 +2480,7 @@ bool RemoteSerializer::ProcessRemotePrint()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool RemoteSerializer::SendLogCreateWriter(EnumVal* id, EnumVal* writer, string path, int num_fields, const LogField* const * fields)
|
||||
bool RemoteSerializer::SendLogCreateWriter(EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Field* const * fields)
|
||||
{
|
||||
loop_over_list(peers, i)
|
||||
{
|
||||
|
@ -2486,7 +2490,7 @@ bool RemoteSerializer::SendLogCreateWriter(EnumVal* id, EnumVal* writer, string
|
|||
return true;
|
||||
}
|
||||
|
||||
bool RemoteSerializer::SendLogCreateWriter(PeerID peer_id, EnumVal* id, EnumVal* writer, string path, int num_fields, const LogField* const * fields)
|
||||
bool RemoteSerializer::SendLogCreateWriter(PeerID peer_id, EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Field* const * fields)
|
||||
{
|
||||
SetErrorDescr("logging");
|
||||
|
||||
|
@ -2499,6 +2503,9 @@ bool RemoteSerializer::SendLogCreateWriter(PeerID peer_id, EnumVal* id, EnumVal*
|
|||
if ( peer->phase != Peer::HANDSHAKE && peer->phase != Peer::RUNNING )
|
||||
return false;
|
||||
|
||||
if ( ! peer->logs_requested )
|
||||
return false;
|
||||
|
||||
BinarySerializationFormat fmt;
|
||||
|
||||
fmt.StartWrite();
|
||||
|
@ -2540,7 +2547,7 @@ error:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool RemoteSerializer::SendLogWrite(EnumVal* id, EnumVal* writer, string path, int num_fields, const LogVal* const * vals)
|
||||
bool RemoteSerializer::SendLogWrite(EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Value* const * vals)
|
||||
{
|
||||
loop_over_list(peers, i)
|
||||
{
|
||||
|
@ -2550,7 +2557,7 @@ bool RemoteSerializer::SendLogWrite(EnumVal* id, EnumVal* writer, string path, i
|
|||
return true;
|
||||
}
|
||||
|
||||
bool RemoteSerializer::SendLogWrite(Peer* peer, EnumVal* id, EnumVal* writer, string path, int num_fields, const LogVal* const * vals)
|
||||
bool RemoteSerializer::SendLogWrite(Peer* peer, EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Value* const * vals)
|
||||
{
|
||||
if ( peer->phase != Peer::HANDSHAKE && peer->phase != Peer::RUNNING )
|
||||
return false;
|
||||
|
@ -2558,7 +2565,9 @@ bool RemoteSerializer::SendLogWrite(Peer* peer, EnumVal* id, EnumVal* writer, st
|
|||
if ( ! peer->logs_requested )
|
||||
return false;
|
||||
|
||||
assert(peer->log_buffer);
|
||||
if ( ! peer->log_buffer )
|
||||
// Peer shutting down.
|
||||
return false;
|
||||
|
||||
// Serialize the log record entry.
|
||||
|
||||
|
@ -2593,8 +2602,11 @@ bool RemoteSerializer::SendLogWrite(Peer* peer, EnumVal* id, EnumVal* writer, st
|
|||
if ( len > (LOG_BUFFER_SIZE - peer->log_buffer_used) || (network_time - last_flush > 1.0) )
|
||||
{
|
||||
if ( ! FlushLogBuffer(peer) )
|
||||
{
|
||||
delete [] data;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If the data is actually larger than our complete buffer, just send it out.
|
||||
if ( len > LOG_BUFFER_SIZE )
|
||||
|
@ -2616,6 +2628,9 @@ error:
|
|||
|
||||
bool RemoteSerializer::FlushLogBuffer(Peer* p)
|
||||
{
|
||||
if ( ! p->logs_requested )
|
||||
return false;
|
||||
|
||||
last_flush = network_time;
|
||||
|
||||
if ( p->state == Peer::CLOSING )
|
||||
|
@ -2637,11 +2652,17 @@ bool RemoteSerializer::ProcessLogCreateWriter()
|
|||
if ( current_peer->state == Peer::CLOSING )
|
||||
return false;
|
||||
|
||||
#ifdef USE_PERFTOOLS_DEBUG
|
||||
// Don't track allocations here, they'll be released only after the
|
||||
// main loop exists. And it's just a tiny amount anyway.
|
||||
HeapLeakChecker::Disabler disabler;
|
||||
#endif
|
||||
|
||||
assert(current_args);
|
||||
|
||||
EnumVal* id_val = 0;
|
||||
EnumVal* writer_val = 0;
|
||||
LogField** fields = 0;
|
||||
threading::Field** fields = 0;
|
||||
|
||||
BinarySerializationFormat fmt;
|
||||
fmt.StartRead(current_args->data, current_args->len);
|
||||
|
@ -2658,11 +2679,11 @@ bool RemoteSerializer::ProcessLogCreateWriter()
|
|||
if ( ! success )
|
||||
goto error;
|
||||
|
||||
fields = new LogField* [num_fields];
|
||||
fields = new threading::Field* [num_fields];
|
||||
|
||||
for ( int i = 0; i < num_fields; i++ )
|
||||
{
|
||||
fields[i] = new LogField;
|
||||
fields[i] = new threading::Field;
|
||||
if ( ! fields[i]->Read(&fmt) )
|
||||
goto error;
|
||||
}
|
||||
|
@ -2672,7 +2693,7 @@ bool RemoteSerializer::ProcessLogCreateWriter()
|
|||
id_val = new EnumVal(id, BifType::Enum::Log::ID);
|
||||
writer_val = new EnumVal(writer, BifType::Enum::Log::Writer);
|
||||
|
||||
if ( ! log_mgr->CreateWriter(id_val, writer_val, path, num_fields, fields) )
|
||||
if ( ! log_mgr->CreateWriter(id_val, writer_val, path, num_fields, fields, true, false) )
|
||||
goto error;
|
||||
|
||||
Unref(id_val);
|
||||
|
@ -2703,7 +2724,7 @@ bool RemoteSerializer::ProcessLogWrite()
|
|||
// Unserialize one entry.
|
||||
EnumVal* id_val = 0;
|
||||
EnumVal* writer_val = 0;
|
||||
LogVal** vals = 0;
|
||||
threading::Value** vals = 0;
|
||||
|
||||
int id, writer;
|
||||
string path;
|
||||
|
@ -2717,11 +2738,11 @@ bool RemoteSerializer::ProcessLogWrite()
|
|||
if ( ! success )
|
||||
goto error;
|
||||
|
||||
vals = new LogVal* [num_fields];
|
||||
vals = new threading::Value* [num_fields];
|
||||
|
||||
for ( int i = 0; i < num_fields; i++ )
|
||||
{
|
||||
vals[i] = new LogVal;
|
||||
vals[i] = new threading::Value;
|
||||
if ( ! vals[i]->Read(&fmt) )
|
||||
goto error;
|
||||
}
|
||||
|
@ -2741,6 +2762,8 @@ bool RemoteSerializer::ProcessLogWrite()
|
|||
|
||||
fmt.EndRead();
|
||||
|
||||
++received_logs;
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
|
@ -2850,7 +2873,7 @@ void RemoteSerializer::GotID(ID* id, Val* val)
|
|||
(desc && *desc) ? desc : "not set"),
|
||||
current_peer);
|
||||
|
||||
#ifdef USE_PERFTOOLS
|
||||
#ifdef USE_PERFTOOLS_DEBUG
|
||||
// May still be cached, but we don't care.
|
||||
heap_checker->IgnoreObject(id);
|
||||
#endif
|
||||
|
@ -3382,6 +3405,11 @@ void SocketComm::Run()
|
|||
small_timeout.tv_usec =
|
||||
io->CanWrite() || io->CanRead() ? 1 : 10;
|
||||
|
||||
#if 0
|
||||
if ( ! io->CanWrite() )
|
||||
usleep(10);
|
||||
#endif
|
||||
|
||||
int a = select(max_fd + 1, &fd_read, &fd_write, &fd_except,
|
||||
&small_timeout);
|
||||
|
||||
|
|
|
@ -14,8 +14,11 @@
|
|||
// FIXME: Change this to network byte order
|
||||
|
||||
class IncrementalSendTimer;
|
||||
class LogField;
|
||||
class LogVal;
|
||||
|
||||
namespace threading {
|
||||
class Field;
|
||||
class Value;
|
||||
}
|
||||
|
||||
// This class handles the communication done in Bro's main loop.
|
||||
class RemoteSerializer : public Serializer, public IOSource {
|
||||
|
@ -32,7 +35,7 @@ public:
|
|||
static const PeerID PEER_NONE = SOURCE_LOCAL;
|
||||
|
||||
// Connect to host (returns PEER_NONE on error).
|
||||
PeerID Connect(addr_type ip, uint16 port, const char* our_class, double retry, bool use_ssl);
|
||||
PeerID Connect(const IPAddr& ip, uint16 port, const char* our_class, double retry, bool use_ssl);
|
||||
|
||||
// Close connection to host.
|
||||
bool CloseConnection(PeerID peer);
|
||||
|
@ -60,7 +63,7 @@ public:
|
|||
bool CompleteHandshake(PeerID peer);
|
||||
|
||||
// Start to listen.
|
||||
bool Listen(addr_type ip, uint16 port, bool expect_ssl);
|
||||
bool Listen(const IPAddr& ip, uint16 port, bool expect_ssl);
|
||||
|
||||
// Stop it.
|
||||
bool StopListening();
|
||||
|
@ -99,13 +102,13 @@ public:
|
|||
bool SendPrintHookEvent(BroFile* f, const char* txt, size_t len);
|
||||
|
||||
// Send a request to create a writer on a remote side.
|
||||
bool SendLogCreateWriter(PeerID peer, EnumVal* id, EnumVal* writer, string path, int num_fields, const LogField* const * fields);
|
||||
bool SendLogCreateWriter(PeerID peer, EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Field* const * fields);
|
||||
|
||||
// Broadcasts a request to create a writer.
|
||||
bool SendLogCreateWriter(EnumVal* id, EnumVal* writer, string path, int num_fields, const LogField* const * fields);
|
||||
bool SendLogCreateWriter(EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Field* const * fields);
|
||||
|
||||
// Broadcast a log entry to everybody interested.
|
||||
bool SendLogWrite(EnumVal* id, EnumVal* writer, string path, int num_fields, const LogVal* const * vals);
|
||||
bool SendLogWrite(EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Value* const * vals);
|
||||
|
||||
// Synchronzizes time with all connected peers. Returns number of
|
||||
// current sync-point, or -1 on error.
|
||||
|
@ -300,7 +303,7 @@ protected:
|
|||
bool SendID(SerialInfo* info, Peer* peer, const ID& id);
|
||||
bool SendCapabilities(Peer* peer);
|
||||
bool SendPacket(SerialInfo* info, Peer* peer, const Packet& p);
|
||||
bool SendLogWrite(Peer* peer, EnumVal* id, EnumVal* writer, string path, int num_fields, const LogVal* const * vals);
|
||||
bool SendLogWrite(Peer* peer, EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Value* const * vals);
|
||||
|
||||
void UnregisterHandlers(Peer* peer);
|
||||
void RaiseEvent(EventHandlerPtr event, Peer* peer, const char* arg = 0);
|
||||
|
@ -335,6 +338,7 @@ private:
|
|||
int propagate_accesses;
|
||||
bool ignore_accesses;
|
||||
bool terminating;
|
||||
int received_logs;
|
||||
Peer* source_peer;
|
||||
PeerID id_counter; // Keeps track of assigned IDs.
|
||||
uint32 current_sync_point;
|
||||
|
|
|
@ -155,7 +155,7 @@ void Reporter::WeirdHelper(EventHandlerPtr event, Val* conn_val, const char* add
|
|||
delete vl;
|
||||
}
|
||||
|
||||
void Reporter::WeirdFlowHelper(const uint32* orig, const uint32* resp, const char* fmt_name, ...)
|
||||
void Reporter::WeirdFlowHelper(const IPAddr& orig, const IPAddr& resp, const char* fmt_name, ...)
|
||||
{
|
||||
val_list* vl = new val_list(2);
|
||||
vl->append(new AddrVal(orig));
|
||||
|
@ -184,7 +184,7 @@ void Reporter::Weird(Val* conn_val, const char* name, const char* addl)
|
|||
WeirdHelper(conn_weird, conn_val, addl, "%s", name);
|
||||
}
|
||||
|
||||
void Reporter::Weird(const uint32* orig, const uint32* resp, const char* name)
|
||||
void Reporter::Weird(const IPAddr& orig, const IPAddr& resp, const char* name)
|
||||
{
|
||||
WeirdFlowHelper(orig, resp, "%s", name);
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
#include <utility>
|
||||
|
||||
#include "util.h"
|
||||
#include "net_util.h"
|
||||
#include "EventHandler.h"
|
||||
#include "IPAddr.h"
|
||||
|
||||
class Connection;
|
||||
class Location;
|
||||
|
@ -74,7 +74,7 @@ public:
|
|||
void Weird(const char* name); // Raises net_weird().
|
||||
void Weird(Connection* conn, const char* name, const char* addl = ""); // Raises conn_weird().
|
||||
void Weird(Val* conn_val, const char* name, const char* addl = ""); // Raises conn_weird().
|
||||
void Weird(const uint32* orig, const uint32* resp, const char* name); // Raises flow_weird().
|
||||
void Weird(const IPAddr& orig, const IPAddr& resp, const char* name); // Raises flow_weird().
|
||||
|
||||
// Syslog a message. This methods does nothing if we're running
|
||||
// offline from a trace.
|
||||
|
@ -121,7 +121,7 @@ private:
|
|||
// The order if addl, name needs to be like that since fmt_name can
|
||||
// contain format specifiers
|
||||
void WeirdHelper(EventHandlerPtr event, Val* conn_val, const char* addl, const char* fmt_name, ...);
|
||||
void WeirdFlowHelper(const uint32* orig, const uint32* resp, const char* fmt_name, ...);
|
||||
void WeirdFlowHelper(const IPAddr& orig, const IPAddr& resp, const char* fmt_name, ...);
|
||||
|
||||
int errors;
|
||||
bool via_events;
|
||||
|
|
|
@ -73,6 +73,9 @@ RuleHdrTest::RuleHdrTest(RuleHdrTest& h)
|
|||
copied_set->ids = orig_set->ids;
|
||||
loop_over_list(orig_set->patterns, l)
|
||||
copied_set->patterns.append(copy_string(orig_set->patterns[l]));
|
||||
delete copied_set;
|
||||
// TODO: Why do we create copied_set only to then
|
||||
// never use it?
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,7 +191,7 @@ void RuleMatcher::Delete(RuleHdrTest* node)
|
|||
|
||||
bool RuleMatcher::ReadFiles(const name_list& files)
|
||||
{
|
||||
#ifdef USE_PERFTOOLS
|
||||
#ifdef USE_PERFTOOLS_DEBUG
|
||||
HeapLeakChecker::Disabler disabler;
|
||||
#endif
|
||||
|
||||
|
@ -1067,16 +1070,22 @@ static bool val_to_maskedval(Val* v, maskedvalue_list* append_to)
|
|||
break;
|
||||
|
||||
case TYPE_SUBNET:
|
||||
#ifdef BROv6
|
||||
{
|
||||
uint32* n = v->AsSubNet()->net;
|
||||
uint32* m = v->AsSubNetVal()->Mask();
|
||||
const uint32* n;
|
||||
uint32 m[4];
|
||||
v->AsSubNet().Prefix().GetBytes(&n);
|
||||
v->AsSubNetVal()->Mask().CopyIPv6(m);
|
||||
|
||||
for ( unsigned int i = 0; i < 4; ++i )
|
||||
m[i] = ntohl(m[i]);
|
||||
|
||||
bool is_v4_mask = m[0] == 0xffffffff &&
|
||||
m[1] == m[0] && m[2] == m[0];
|
||||
|
||||
if ( is_v4_addr(n) && is_v4_mask )
|
||||
if ( v->AsSubNet().Prefix().GetFamily() == IPv4 &&
|
||||
is_v4_mask )
|
||||
{
|
||||
mval->val = ntohl(to_v4_addr(n));
|
||||
mval->val = ntohl(*n);
|
||||
mval->mask = m[3];
|
||||
}
|
||||
|
||||
|
@ -1087,10 +1096,6 @@ static bool val_to_maskedval(Val* v, maskedvalue_list* append_to)
|
|||
mval->mask = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
mval->val = ntohl(v->AsSubNet()->net);
|
||||
mval->mask = v->AsSubNetVal()->Mask();
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1114,9 +1119,14 @@ void id_to_maskedvallist(const char* id, maskedvalue_list* append_to)
|
|||
val_list* vals = v->AsTableVal()->ConvertToPureList()->Vals();
|
||||
loop_over_list(*vals, i )
|
||||
if ( ! val_to_maskedval((*vals)[i], append_to) )
|
||||
{
|
||||
delete_vals(vals);
|
||||
return;
|
||||
}
|
||||
|
||||
delete_vals(vals);
|
||||
}
|
||||
|
||||
else
|
||||
val_to_maskedval(v, append_to);
|
||||
}
|
||||
|
|
|
@ -353,7 +353,6 @@ void SMTP_Analyzer::ProcessLine(int length, const char* line, bool orig)
|
|||
int ext_len;
|
||||
|
||||
get_word(end_of_line - line, line, ext_len, ext);
|
||||
line = skip_whitespace(line + ext_len, end_of_line);
|
||||
ProcessExtension(ext_len, ext);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,8 @@ void SSH_Analyzer::DeliverStream(int length, const u_char* data, bool is_orig)
|
|||
{
|
||||
if ( length >= i )
|
||||
{
|
||||
const uint32* dst;
|
||||
IPAddr dst;
|
||||
|
||||
if ( is_orig )
|
||||
dst = TCP()->Orig()->dst_addr;
|
||||
else
|
||||
|
|
|
@ -125,7 +125,7 @@ SERIAL_EXPR(FIELD_EXPR, 22)
|
|||
SERIAL_EXPR(HAS_FIELD_EXPR, 23)
|
||||
SERIAL_EXPR(RECORD_CONSTRUCTOR_EXPR, 24)
|
||||
SERIAL_EXPR(FIELD_ASSIGN_EXPR, 25)
|
||||
SERIAL_EXPR(RECORD_MATCH_EXPR, 26)
|
||||
// There used to be a SERIAL_EXPR(RECORD_MATCH_EXPR, 26) here
|
||||
SERIAL_EXPR(ARITH_COERCE_EXPR, 27)
|
||||
SERIAL_EXPR(RECORD_COERCE_EXPR, 28)
|
||||
SERIAL_EXPR(FLATTEN_EXPR, 29)
|
||||
|
|
|
@ -230,6 +230,71 @@ bool BinarySerializationFormat::Read(string* v, const char* tag)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BinarySerializationFormat::Read(IPAddr* addr, const char* tag)
|
||||
{
|
||||
int n = 0;
|
||||
if ( ! Read(&n, "addr-len") )
|
||||
return false;
|
||||
|
||||
if ( n != 1 && n != 4 )
|
||||
return false;
|
||||
|
||||
uint32_t raw[4];
|
||||
|
||||
for ( int i = 0; i < n; ++i )
|
||||
{
|
||||
if ( ! Read(&raw[i], "addr-part") )
|
||||
return false;
|
||||
|
||||
raw[i] = htonl(raw[i]);
|
||||
}
|
||||
|
||||
if ( n == 1 )
|
||||
*addr = IPAddr(IPv4, raw, IPAddr::Network);
|
||||
else
|
||||
*addr = IPAddr(IPv6, raw, IPAddr::Network);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BinarySerializationFormat::Read(IPPrefix* prefix, const char* tag)
|
||||
{
|
||||
IPAddr addr;
|
||||
int len;
|
||||
|
||||
if ( ! (Read(&addr, "prefix") && Read(&len, "width")) )
|
||||
return false;
|
||||
|
||||
*prefix = IPPrefix(addr, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BinarySerializationFormat::Read(struct in_addr* addr, const char* tag)
|
||||
{
|
||||
uint32_t* bytes = (uint32_t*) &addr->s_addr;
|
||||
|
||||
if ( ! Read(&bytes[0], "addr4") )
|
||||
return false;
|
||||
|
||||
bytes[0] = htonl(bytes[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BinarySerializationFormat::Read(struct in6_addr* addr, const char* tag)
|
||||
{
|
||||
uint32_t* bytes = (uint32_t*) &addr->s6_addr;
|
||||
|
||||
for ( int i = 0; i < 4; ++i )
|
||||
{
|
||||
if ( ! Read(&bytes[i], "addr6-part") )
|
||||
return false;
|
||||
|
||||
bytes[i] = htonl(bytes[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BinarySerializationFormat::Write(char v, const char* tag)
|
||||
{
|
||||
DBG_LOG(DBG_SERIAL, "Write char %s [%s]", fmt_bytes(&v, 1), tag);
|
||||
|
@ -299,6 +364,53 @@ bool BinarySerializationFormat::Write(const string& s, const char* tag)
|
|||
return Write(s.data(), s.size(), tag);
|
||||
}
|
||||
|
||||
bool BinarySerializationFormat::Write(const IPAddr& addr, const char* tag)
|
||||
{
|
||||
const uint32_t* raw;
|
||||
int n = addr.GetBytes(&raw);
|
||||
|
||||
assert(n == 1 || n == 4);
|
||||
|
||||
if ( ! Write(n, "addr-len") )
|
||||
return false;
|
||||
|
||||
for ( int i = 0; i < n; ++i )
|
||||
{
|
||||
if ( ! Write(ntohl(raw[i]), "addr-part") )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BinarySerializationFormat::Write(const IPPrefix& prefix, const char* tag)
|
||||
{
|
||||
return Write(prefix.Prefix(), "prefix") && Write(prefix.Length(), "width");
|
||||
}
|
||||
|
||||
bool BinarySerializationFormat::Write(const struct in_addr& addr, const char* tag)
|
||||
{
|
||||
const uint32_t* bytes = (uint32_t*) &addr.s_addr;
|
||||
|
||||
if ( ! Write(ntohl(bytes[0]), "addr4") )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BinarySerializationFormat::Write(const struct in6_addr& addr, const char* tag)
|
||||
{
|
||||
const uint32_t* bytes = (uint32_t*) &addr.s6_addr;
|
||||
|
||||
for ( int i = 0; i < 4; ++i )
|
||||
{
|
||||
if ( ! Write(ntohl(bytes[i]), "addr6-part") )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BinarySerializationFormat::WriteOpenTag(const char* tag)
|
||||
{
|
||||
return true;
|
||||
|
@ -389,6 +501,30 @@ bool XMLSerializationFormat::Read(string* s, const char* tag)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool XMLSerializationFormat::Read(IPAddr* addr, const char* tag)
|
||||
{
|
||||
reporter->InternalError("no reading of xml");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XMLSerializationFormat::Read(IPPrefix* prefix, const char* tag)
|
||||
{
|
||||
reporter->InternalError("no reading of xml");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XMLSerializationFormat::Read(struct in_addr* addr, const char* tag)
|
||||
{
|
||||
reporter->InternalError("no reading of xml");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XMLSerializationFormat::Read(struct in6_addr* addr, const char* tag)
|
||||
{
|
||||
reporter->InternalError("no reading of xml");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XMLSerializationFormat::Write(char v, const char* tag)
|
||||
{
|
||||
return WriteElem(tag, "char", &v, 1);
|
||||
|
@ -469,6 +605,30 @@ bool XMLSerializationFormat::Write(const char* buf, int len, const char* tag)
|
|||
return WriteElem(tag, "string", buf, len);
|
||||
}
|
||||
|
||||
bool XMLSerializationFormat::Write(const IPAddr& addr, const char* tag)
|
||||
{
|
||||
reporter->InternalError("XML output of addresses not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XMLSerializationFormat::Write(const IPPrefix& prefix, const char* tag)
|
||||
{
|
||||
reporter->InternalError("XML output of prefixes not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XMLSerializationFormat::Write(const struct in_addr& addr, const char* tag)
|
||||
{
|
||||
reporter->InternalError("XML output of in_addr not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XMLSerializationFormat::Write(const struct in6_addr& addr, const char* tag)
|
||||
{
|
||||
reporter->InternalError("XML output of in6_addr not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XMLSerializationFormat::WriteEncodedString(const char* s, int len)
|
||||
{
|
||||
while ( len-- )
|
||||
|
|
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