mirror of
https://github.com/zeek/zeek.git
synced 2025-10-06 08:38:20 +00:00
Significant edit pass over ICMPv6 code.
Matti, more per mail.
This commit is contained in:
parent
cb64bb6874
commit
50181edd84
10 changed files with 424 additions and 719 deletions
|
@ -28,6 +28,8 @@ type icmp_conn: record {
|
||||||
itype: count;
|
itype: count;
|
||||||
icode: count;
|
icode: count;
|
||||||
len: count;
|
len: count;
|
||||||
|
|
||||||
|
v6: bool; # true if it's an ICMPv6 packet.
|
||||||
};
|
};
|
||||||
|
|
||||||
type icmp_hdr: record {
|
type icmp_hdr: record {
|
||||||
|
@ -38,12 +40,11 @@ type icmp_context: record {
|
||||||
id: conn_id;
|
id: conn_id;
|
||||||
len: count;
|
len: count;
|
||||||
proto: count;
|
proto: count;
|
||||||
frag_offset: count &optional; #no frag offset for IPv6
|
bad_hdr_len: bool;
|
||||||
bad_hdr_len: bool &optional;
|
bad_checksum: bool; # always true for ICMPv6.
|
||||||
bad_checksum: bool &optional; #no checksum in IPv6 header
|
frag_offset: count; # always 0 for IMCPv6.
|
||||||
MF: bool &optional; #no MF for IPv6
|
MF: bool; # always false for IMCPv6.
|
||||||
DF: bool &optional; #no DF for IPv6
|
DF: bool; # always true for ICMPv6.
|
||||||
ICMP6Flag: bool;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type addr_set: set[addr];
|
type addr_set: set[addr];
|
||||||
|
|
241
policy/icmp.bro
241
policy/icmp.bro
|
@ -1,5 +1,4 @@
|
||||||
# $Id: icmp.bro 6883 2009-08-19 21:08:09Z vern $
|
# $Id: icmp.bro 6883 2009-08-19 21:08:09Z vern $
|
||||||
# While using this script, please notice that the last F/T value is the IPv6 Flag
|
|
||||||
|
|
||||||
@load hot
|
@load hot
|
||||||
@load weird
|
@load weird
|
||||||
|
@ -18,6 +17,7 @@ export {
|
||||||
ICMPAsymPayload, # payload in echo req-resp not the same
|
ICMPAsymPayload, # payload in echo req-resp not the same
|
||||||
ICMPConnectionPair, # too many ICMPs between hosts
|
ICMPConnectionPair, # too many ICMPs between hosts
|
||||||
ICMPAddressScan,
|
ICMPAddressScan,
|
||||||
|
ICMPRogueRouter, # v6 advertisement from unknown router
|
||||||
|
|
||||||
# The following isn't presently sufficiently useful due
|
# The following isn't presently sufficiently useful due
|
||||||
# to cold start and packet drops.
|
# to cold start and packet drops.
|
||||||
|
@ -35,6 +35,12 @@ export {
|
||||||
const detect_conn_pairs = F &redef; # switch for connection pair
|
const detect_conn_pairs = F &redef; # switch for connection pair
|
||||||
const detect_payload_asym = F &redef; # switch for echo payload
|
const detect_payload_asym = F &redef; # switch for echo payload
|
||||||
const conn_pair_threshold = 200 &redef;
|
const conn_pair_threshold = 200 &redef;
|
||||||
|
|
||||||
|
# If the IPv6 routers in a network are all known, they can be
|
||||||
|
# whitelisted here. If so, any other router seen sending an
|
||||||
|
# announcement will be reported. If this set remains empty, no such
|
||||||
|
# detection will be done.
|
||||||
|
const router_whitelist: set[addr] &redef;
|
||||||
}
|
}
|
||||||
|
|
||||||
global conn_pair:table[addr] of set[addr] &create_expire = 1 day;
|
global conn_pair:table[addr] of set[addr] &create_expire = 1 day;
|
||||||
|
@ -56,16 +62,10 @@ type flow_info: record {
|
||||||
payload: string;
|
payload: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
#Insert whitelisted routers here, Router advertisements from other
|
|
||||||
#routers will be logged as possible rogue router attacks
|
|
||||||
const routers_whitelist: table[string] of bool = {
|
|
||||||
#["fe80::260:97ff:fe07:69ea"] = T, #an example
|
|
||||||
} &redef &default = F;
|
|
||||||
|
|
||||||
const names: table[count] of string = {
|
const names: table[count] of string = {
|
||||||
[0] = "echo_reply",
|
[0] = "echo_reply",
|
||||||
[1] = "unreach", #icmpv6
|
[1] = "unreach", # icmpv6
|
||||||
[2] = "too_big", #icmpv6
|
[2] = "too_big", # icmpv6
|
||||||
[3] = "unreach",
|
[3] = "unreach",
|
||||||
[4] = "quench",
|
[4] = "quench",
|
||||||
[5] = "redirect",
|
[5] = "redirect",
|
||||||
|
@ -80,33 +80,33 @@ const names: table[count] of string = {
|
||||||
[16] = "info_reply",
|
[16] = "info_reply",
|
||||||
[17] = "mask_req",
|
[17] = "mask_req",
|
||||||
[18] = "mask_reply",
|
[18] = "mask_reply",
|
||||||
[128] = "echo_req", #icmpv6
|
[128] = "echo_req", # icmpv6
|
||||||
[129] = "echo_reply", #icmpv6
|
[129] = "echo_reply", # icmpv6
|
||||||
[130] = "group_memb_query", #icmpv6
|
[130] = "group_memb_query", # icmpv6
|
||||||
[131] = "group_memb_report", #icmpv6
|
[131] = "group_memb_report", # icmpv6
|
||||||
[132] = "group_memb_reduct", #icmpv6
|
[132] = "group_memb_reduct", # icmpv6
|
||||||
[133] = "router_sol", #icmpv6
|
[133] = "router_sol", # icmpv6
|
||||||
[134] = "router_ad", #icmpv6
|
[134] = "router_ad", # icmpv6
|
||||||
[135] = "neighbor_sol", #icmpv6
|
[135] = "neighbor_sol", # icmpv6
|
||||||
[136] = "neighbor_ad", #icmpv6
|
[136] = "neighbor_ad", # icmpv6
|
||||||
[137] = "redirect", #icmpv6
|
[137] = "redirect", # icmpv6
|
||||||
[138] = "router_renum", #icmpv6
|
[138] = "router_renum", # icmpv6
|
||||||
[139] = "node_info_query", #icmpv6
|
[139] = "node_info_query", # icmpv6
|
||||||
[140] = "node_info_resp", #icmpv6
|
[140] = "node_info_resp", # icmpv6
|
||||||
[141] = "inv_neigh_disc_sol", #icmpv6
|
[141] = "inv_neigh_disc_sol", # icmpv6
|
||||||
[142] = "inv_neigh_disc_ad", #icmpv6
|
[142] = "inv_neigh_disc_ad", # icmpv6
|
||||||
[143] = "mul_lis_report", #icmpv6
|
[143] = "mul_lis_report", # icmpv6
|
||||||
[144] = "home_agent_addr_req", #icmpv6
|
[144] = "home_agent_addr_req", # icmpv6
|
||||||
[145] = "home_agent_addr_reply",#icmpv6
|
[145] = "home_agent_addr_reply",# icmpv6
|
||||||
[146] = "mobible_prefx_sol", #icmpv6
|
[146] = "mobible_prefx_sol", # icmpv6
|
||||||
[147] = "mobible_prefx_ad", #icmpv6
|
[147] = "mobible_prefx_ad", # icmpv6
|
||||||
[148] = "cert_path_sol", #icmpv6
|
[148] = "cert_path_sol", # icmpv6
|
||||||
[149] = "cert_path_ad", #icmpv6
|
[149] = "cert_path_ad", # icmpv6
|
||||||
[150] = "experimental", #icmpv6
|
[150] = "experimental", # icmpv6
|
||||||
[151] = "mcast_router_ad", #icmpv6
|
[151] = "mcast_router_ad", # icmpv6
|
||||||
[152] = "mcast_router_sol", #icmpv6
|
[152] = "mcast_router_sol", # icmpv6
|
||||||
[153] = "mcast_router_term", #icmpv6
|
[153] = "mcast_router_term", # icmpv6
|
||||||
[154] = "fmip", #icmpv6
|
[154] = "fmip", # icmpv6
|
||||||
} &default = function(n: count): string { return fmt("icmp-%d", n); };
|
} &default = function(n: count): string { return fmt("icmp-%d", n); };
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,8 +116,8 @@ const IP_proto_name: table[count] of string = {
|
||||||
[2] = "IGMP",
|
[2] = "IGMP",
|
||||||
[6] = "TCP",
|
[6] = "TCP",
|
||||||
[17] = "UDP",
|
[17] = "UDP",
|
||||||
[41] = "IP6",
|
[41] = "IPV6",
|
||||||
[58] = "ICMP6",
|
[58] = "ICMPV6",
|
||||||
} &default = function(n: count): string { return fmt("%s", n); }
|
} &default = function(n: count): string { return fmt("%s", n); }
|
||||||
&redef;
|
&redef;
|
||||||
|
|
||||||
|
@ -160,13 +160,38 @@ global flows: table[flow_id] of flow_info
|
||||||
&read_expire = 45 sec
|
&read_expire = 45 sec
|
||||||
&expire_func = flush_flow;
|
&expire_func = flush_flow;
|
||||||
|
|
||||||
event icmp_sent(c: connection, icmp: icmp_conn, ICMP6: bool)
|
function print_log(c: connection, icmp: icmp_conn, addl: string)
|
||||||
{
|
{
|
||||||
|
if ( ! log_details )
|
||||||
|
return;
|
||||||
|
|
||||||
print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s %s",
|
print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s",
|
||||||
network_time(), 0.0, icmp$orig_h, icmp$resp_h,
|
network_time(), 0.0, icmp$orig_h, icmp$resp_h,
|
||||||
names[icmp$itype], icmp$itype, icmp$icode, "icmp",
|
names[icmp$itype], icmp$itype, icmp$icode,
|
||||||
icmp$len, "0", "SH", ICMP6);
|
icmp$v6 ? "icmp6" : "icmp", icmp$len, addl);
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_log_with_context(c: connection, icmp: icmp_conn, context: icmp_context, addl: string)
|
||||||
|
{
|
||||||
|
# Due to the connection data contained *within*
|
||||||
|
# them, each log line will contain two connections' worth
|
||||||
|
# of data. The initial ICMP connection info is the same
|
||||||
|
# as logged for connections.
|
||||||
|
|
||||||
|
local ctx = fmt("0 EncapPkt: %s %s %s %s %s %s %s %s %s",
|
||||||
|
context$id$orig_h, context$id$orig_p,
|
||||||
|
context$id$resp_h, context$id$resp_p,
|
||||||
|
context$len, IP_proto_name[context$proto],
|
||||||
|
context$len, context$bad_hdr_len,
|
||||||
|
context$bad_checksum);
|
||||||
|
|
||||||
|
print_log(c, icmp, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
event icmp_sent(c: connection, icmp: icmp_conn)
|
||||||
|
{
|
||||||
|
print_log(c, icmp, "0 SH");
|
||||||
}
|
}
|
||||||
|
|
||||||
event flow_summary(flow: flow_id, last_time: time)
|
event flow_summary(flow: flow_id, last_time: time)
|
||||||
|
@ -212,63 +237,18 @@ function update_flow(icmp: icmp_conn, id: count, is_orig: bool, payload: string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
event icmp_error_message(c: connection, icmp: icmp_conn, code: count, context: icmp_context) #for other but the unreach types, which is preserved
|
event icmp_error_message(c: connection, icmp: icmp_conn, code: count, context: icmp_context)
|
||||||
{
|
{
|
||||||
|
print_log_with_context(c, icmp, context, "");
|
||||||
if ( active_connection(context$id) )
|
|
||||||
{
|
|
||||||
# This section allows Bro to act on ICMP error message packets
|
|
||||||
# that happen in the context of an active connection. It is
|
|
||||||
# not currently used.
|
|
||||||
local c2 = connection_record(context$id);
|
|
||||||
local os = c2$orig$state;
|
|
||||||
local rs = c2$resp$state;
|
|
||||||
local is_attempt =
|
|
||||||
is_tcp_port(c2$id$orig_p) ?
|
|
||||||
(os == TCP_SYN_SENT && rs == TCP_INACTIVE) :
|
|
||||||
(os == UDP_ACTIVE && rs == UDP_INACTIVE);
|
|
||||||
|
|
||||||
# Insert action here.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( log_details )
|
event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string)
|
||||||
{
|
|
||||||
# ICMP error message packets are logged here.
|
|
||||||
# Due to the connection data contained *within*
|
|
||||||
# them, each log line will contain two connections' worth
|
|
||||||
# of data. The initial ICMP connection info is the same
|
|
||||||
# as logged for connections.
|
|
||||||
print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s",
|
|
||||||
network_time(), 0.0, icmp$orig_h, icmp$resp_h,
|
|
||||||
names[icmp$itype], icmp$itype, icmp$icode, "icmp",
|
|
||||||
icmp$len, "0", "EncapPkt:",
|
|
||||||
# This is the encapsulated packet:
|
|
||||||
context$id$orig_h, context$id$orig_p,
|
|
||||||
context$id$resp_h, context$id$resp_p,
|
|
||||||
context$len, IP_proto_name[context$proto],
|
|
||||||
context$len, context$bad_hdr_len,
|
|
||||||
context$bad_checksum, context$ICMP6Flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
event icmp6_placeholder(c: connection, icmp: icmp_conn, ICMP6: bool) #just for testing
|
|
||||||
{
|
|
||||||
print "icmp6_placeholder triggered";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string, ICMP6: bool)
|
|
||||||
{
|
{
|
||||||
update_flow(icmp, id, T, payload);
|
update_flow(icmp, id, T, payload);
|
||||||
|
|
||||||
|
|
||||||
local orig = icmp$orig_h;
|
local orig = icmp$orig_h;
|
||||||
local resp = icmp$resp_h;
|
local resp = icmp$resp_h;
|
||||||
|
|
||||||
|
|
||||||
# Simple ping scan detector.
|
# Simple ping scan detector.
|
||||||
if ( detect_scans &&
|
if ( detect_scans &&
|
||||||
(orig !in Scan::distinct_peers ||
|
(orig !in Scan::distinct_peers ||
|
||||||
|
@ -320,7 +300,7 @@ event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, p
|
||||||
}
|
}
|
||||||
|
|
||||||
event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count,
|
event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count,
|
||||||
seq: count, payload: string, ICMP6: bool)
|
seq: count, payload: string)
|
||||||
{
|
{
|
||||||
# Check payload with the associated flow.
|
# Check payload with the associated flow.
|
||||||
|
|
||||||
|
@ -329,8 +309,6 @@ event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count,
|
||||||
fid$resp_h = icmp$orig_h; # it's an echo reply.
|
fid$resp_h = icmp$orig_h; # it's an echo reply.
|
||||||
fid$id = id;
|
fid$id = id;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ( fid !in flows )
|
if ( fid !in flows )
|
||||||
{
|
{
|
||||||
# NOTICE([$note=ICMPUnpairedEchoReply,
|
# NOTICE([$note=ICMPUnpairedEchoReply,
|
||||||
|
@ -357,78 +335,19 @@ event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count,
|
||||||
update_flow(icmp, id, F, payload);
|
update_flow(icmp, id, F, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
event icmp_unreachable(c: connection, icmp: icmp_conn, code: count,
|
event icmp_unreachable(c: connection, icmp: icmp_conn, code: count,
|
||||||
context: icmp_context)
|
context: icmp_context)
|
||||||
{
|
{
|
||||||
|
print_log_with_context(c, icmp, context, "");
|
||||||
|
}
|
||||||
|
|
||||||
if ( active_connection(context$id) )
|
event icmp_router_advertisement(c: connection, icmp: icmp_conn)
|
||||||
{
|
{
|
||||||
# This section allows Bro to act on ICMP-unreachable packets
|
print_log(c, icmp, "");
|
||||||
# that happen in the context of an active connection. It is
|
|
||||||
# not currently used.
|
|
||||||
local c2 = connection_record(context$id);
|
|
||||||
local os = c2$orig$state;
|
|
||||||
local rs = c2$resp$state;
|
|
||||||
local is_attempt =
|
|
||||||
is_tcp_port(c2$id$orig_p) ?
|
|
||||||
(os == TCP_SYN_SENT && rs == TCP_INACTIVE) :
|
|
||||||
(os == UDP_ACTIVE && rs == UDP_INACTIVE);
|
|
||||||
|
|
||||||
# Insert action here.
|
if ( |router_whitelist| == 0 || icmp$orig_h in router_whitelist )
|
||||||
|
return;
|
||||||
|
|
||||||
|
NOTICE([$note=ICMPRogueRouter,
|
||||||
|
$msg=fmt("rouge router advertisement from %s", icmp$orig_h)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( log_details )
|
|
||||||
{
|
|
||||||
# ICMP unreachable packets are the only ones currently
|
|
||||||
# logged. Due to the connection data contained *within*
|
|
||||||
# them, each log line will contain two connections' worth
|
|
||||||
# of data. The initial ICMP connection info is the same
|
|
||||||
# as logged for connections.
|
|
||||||
print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s",
|
|
||||||
network_time(), 0.0, icmp$orig_h, icmp$resp_h,
|
|
||||||
names[icmp$itype], icmp$itype, icmp$icode, "icmp",
|
|
||||||
icmp$len, "0", "EncapPkt:",
|
|
||||||
# This is the encapsulated packet:
|
|
||||||
context$id$orig_h, context$id$orig_p,
|
|
||||||
context$id$resp_h, context$id$resp_p,
|
|
||||||
context$len, IP_proto_name[context$proto],
|
|
||||||
context$len, context$bad_hdr_len,
|
|
||||||
context$bad_checksum, context$ICMP6Flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
event icmp_router_advertisement(c: connection, icmp: icmp_conn, ICMP6: bool)
|
|
||||||
{
|
|
||||||
if ( routers_whitelist[ fmt("%s",icmp$orig_h) ] )
|
|
||||||
{
|
|
||||||
print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s %s",
|
|
||||||
network_time(), 0.0, icmp$orig_h, icmp$resp_h,
|
|
||||||
names[icmp$itype], icmp$itype, icmp$icode, "icmp",
|
|
||||||
icmp$len, "0", "SH", ICMP6);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s",
|
|
||||||
network_time(), 0.0, icmp$orig_h, icmp$resp_h,
|
|
||||||
names[icmp$itype], "Possible Rogue Router Detected", icmp$itype, icmp$icode,
|
|
||||||
icmp$len, ICMP6);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,20 +48,6 @@ const Analyzer::Config Analyzer::analyzer_configs[] = {
|
||||||
|
|
||||||
{ AnalyzerTag::ICMP, "ICMP", ICMP_Analyzer::InstantiateAnalyzer,
|
{ AnalyzerTag::ICMP, "ICMP", ICMP_Analyzer::InstantiateAnalyzer,
|
||||||
ICMP_Analyzer::Available, 0, false },
|
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::TCP, "TCP", TCP_Analyzer::InstantiateAnalyzer,
|
{ AnalyzerTag::TCP, "TCP", TCP_Analyzer::InstantiateAnalyzer,
|
||||||
TCP_Analyzer::Available, 0, false },
|
TCP_Analyzer::Available, 0, false },
|
||||||
{ AnalyzerTag::UDP, "UDP", UDP_Analyzer::InstantiateAnalyzer,
|
{ AnalyzerTag::UDP, "UDP", UDP_Analyzer::InstantiateAnalyzer,
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace AnalyzerTag {
|
||||||
PIA_TCP, PIA_UDP,
|
PIA_TCP, PIA_UDP,
|
||||||
|
|
||||||
// Transport-layer analyzers.
|
// Transport-layer analyzers.
|
||||||
ICMP,/* ICMP_TimeExceeded, ICMP_Unreachable, ICMP_Echo*/ TCP, UDP,
|
ICMP, TCP, UDP,
|
||||||
|
|
||||||
// Application-layer analyzers (hand-written).
|
// Application-layer analyzers (hand-written).
|
||||||
BitTorrent, BitTorrentTracker,
|
BitTorrent, BitTorrentTracker,
|
||||||
|
|
34
src/DPM.cc
34
src/DPM.cc
|
@ -214,42 +214,8 @@ bool DPM::BuildInitialAnalyzerTree(TransportProto proto, Connection* conn,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRANSPORT_ICMP: {
|
case TRANSPORT_ICMP: {
|
||||||
const struct icmp* icmpp = (const struct icmp *) data;
|
|
||||||
|
|
||||||
|
|
||||||
//Old code, moving to having only one ICMP analyzer
|
|
||||||
/*switch ( icmpp->icmp_type ) {
|
|
||||||
|
|
||||||
case ICMP_ECHO:
|
|
||||||
case ICMP_ECHOREPLY:
|
|
||||||
if ( ICMP_Echo_Analyzer::Available() )
|
|
||||||
{
|
|
||||||
root = new ICMP_Echo_Analyzer(conn);
|
|
||||||
DBG_DPD(conn, "activated ICMP Echo analyzer");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ICMP_UNREACH:
|
|
||||||
if ( ICMP_Unreachable_Analyzer::Available() )
|
|
||||||
{
|
|
||||||
root = new ICMP_Unreachable_Analyzer(conn);
|
|
||||||
DBG_DPD(conn, "activated ICMP Unreachable analyzer");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ICMP_TIMXCEED:
|
|
||||||
if ( ICMP_TimeExceeded_Analyzer::Available() )
|
|
||||||
{
|
|
||||||
root = new ICMP_TimeExceeded_Analyzer(conn);
|
|
||||||
DBG_DPD(conn, "activated ICMP Time Exceeded analyzer");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}*/
|
|
||||||
//if ( ! root )
|
|
||||||
|
|
||||||
root = new ICMP_Analyzer(conn);
|
root = new ICMP_Analyzer(conn);
|
||||||
DBG_DPD(conn, "activated ICMP analyzer");
|
DBG_DPD(conn, "activated ICMP analyzer");
|
||||||
|
|
||||||
analyzed = true;
|
analyzed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
617
src/ICMP.cc
617
src/ICMP.cc
|
@ -11,15 +11,12 @@
|
||||||
|
|
||||||
#include <netinet/icmp6.h>
|
#include <netinet/icmp6.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ICMP_Analyzer::ICMP_Analyzer(Connection* c)
|
ICMP_Analyzer::ICMP_Analyzer(Connection* c)
|
||||||
: TransportLayerAnalyzer(AnalyzerTag::ICMP, c)
|
: TransportLayerAnalyzer(AnalyzerTag::ICMP, c)
|
||||||
{
|
{
|
||||||
icmp_conn_val = 0;
|
icmp_conn_val = 0;
|
||||||
c->SetInactivityTimeout(icmp_inactivity_timeout);
|
c->SetInactivityTimeout(icmp_inactivity_timeout);
|
||||||
request_len = reply_len = -1;
|
request_len = reply_len = -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ICMP_Analyzer::ICMP_Analyzer(AnalyzerTag::Tag tag, Connection* c)
|
ICMP_Analyzer::ICMP_Analyzer(AnalyzerTag::Tag tag, Connection* c)
|
||||||
|
@ -37,7 +34,7 @@ void ICMP_Analyzer::Done()
|
||||||
matcher_state.FinishEndpointMatcher();
|
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)
|
bool is_orig, int seq, const IP_Hdr* ip, int caplen)
|
||||||
{
|
{
|
||||||
assert(ip);
|
assert(ip);
|
||||||
|
@ -50,43 +47,40 @@ void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data,
|
||||||
// Subtract off the common part of ICMP header.
|
// Subtract off the common part of ICMP header.
|
||||||
PacketContents(data + 8, min(len, caplen) - 8);
|
PacketContents(data + 8, min(len, caplen) - 8);
|
||||||
|
|
||||||
|
|
||||||
const struct icmp* icmpp = (const struct icmp*) data;
|
const struct icmp* icmpp = (const struct icmp*) data;
|
||||||
len = arg_len;
|
|
||||||
|
|
||||||
|
assert(caplen >= len); // Should have been caught earlier already.
|
||||||
|
|
||||||
|
if ( ! ignore_checksums )
|
||||||
|
{
|
||||||
|
int chksum;
|
||||||
|
|
||||||
//We need a separate calculation for ICMP6 checksums, pseudoheader is appended to the
|
|
||||||
//ICMP6 checksum calculation, which is different from ICMP4
|
|
||||||
#ifdef BROv6
|
#ifdef BROv6
|
||||||
|
switch ( ip->NextProto() )
|
||||||
|
{
|
||||||
|
case IPPROTO_ICMP:
|
||||||
|
chksum = icmp_checksum(icmpp, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IPPROTO_ICMPV6:
|
||||||
|
chksum = icmp6_checksum(icmpp, ip->IP6_Hdr(), len);
|
||||||
|
break;
|
||||||
|
|
||||||
if (ip->NextProto() == IPPROTO_ICMPV6 && ! ignore_checksums &&
|
default:
|
||||||
caplen >= len && icmp6_checksum(icmpp,ip->IP6_Hdr(),len )!= 0xffff )
|
internal_error("unexpected IP proto in ICMP analyzer");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# Classic v4 version.
|
||||||
|
chksum = icmp_checksum(icmpp, len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( chksum != 0xffff )
|
||||||
{
|
{
|
||||||
Weird("bad_ICMP6_checksum");
|
Weird("bad_ICMP6_checksum");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (ip->NextProto() != IPPROTO_ICMPV6 && ! ignore_checksums &&
|
|
||||||
caplen >= len && icmp_checksum(icmpp, len) != 0xffff )
|
|
||||||
{
|
|
||||||
Weird("bad_ICMP_checksum");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
if ( ! ignore_checksums && caplen >= len &&
|
|
||||||
icmp_checksum(icmpp, len) != 0xffff )
|
|
||||||
{
|
|
||||||
Weird("bad_ICMP_checksum");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Conn()->SetLastTime(current_timestamp);
|
Conn()->SetLastTime(current_timestamp);
|
||||||
|
|
||||||
if ( rule_matcher )
|
if ( rule_matcher )
|
||||||
|
@ -95,89 +89,26 @@ void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data,
|
||||||
matcher_state.InitEndpointMatcher(this, ip, len, is_orig, 0);
|
matcher_state.InitEndpointMatcher(this, ip, len, is_orig, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
type = icmpp->icmp_type;
|
// Move past common portion of ICMP header.
|
||||||
code = icmpp->icmp_code;
|
|
||||||
|
|
||||||
// Move past common portion of ICMP header. //OK for ICMPv6?
|
|
||||||
data += 8;
|
data += 8;
|
||||||
caplen -= 8;
|
caplen -= 8;
|
||||||
len -= 8;
|
len -= 8;
|
||||||
|
|
||||||
int& len_stat = is_orig ? request_len : reply_len;
|
if ( ip->NextProto() == IPPROTO_ICMP )
|
||||||
if ( len_stat < 0 )
|
NextICMP4(current_timestamp, icmpp, len, caplen, data, ip);
|
||||||
len_stat = len;
|
|
||||||
else
|
else
|
||||||
len_stat += len;
|
NextICMP6(current_timestamp, icmpp, len, caplen, data, ip);
|
||||||
|
|
||||||
NextICMP(current_timestamp, icmpp, len, caplen, data, ip);
|
|
||||||
|
|
||||||
if ( rule_matcher )
|
if ( rule_matcher )
|
||||||
matcher_state.Match(Rule::PAYLOAD, data, len, is_orig,
|
matcher_state.Match(Rule::PAYLOAD, data, len, is_orig,
|
||||||
false, false, true);
|
false, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ICMP_Analyzer::NextICMP4(double t, const struct icmp* icmpp, int len, int caplen,
|
||||||
|
|
||||||
/********************Generic analyzer for all ICMP4/ICMP6******************************/
|
|
||||||
void ICMP_Analyzer::NextICMP(double t , const struct icmp* icmpp , int len , int caplen,
|
|
||||||
const u_char*& data, const IP_Hdr* ip_hdr )
|
const u_char*& data, const IP_Hdr* ip_hdr )
|
||||||
{
|
{
|
||||||
int ICMP6Flag = 0;
|
switch ( icmpp->icmp_type )
|
||||||
|
|
||||||
//printf("Executing: ICMP_Analyzer::NextICMP\n");
|
|
||||||
//printf("New analyzer structure\n");
|
|
||||||
|
|
||||||
if ( ip_hdr->NextProto() == IPPROTO_ICMPV6 )
|
|
||||||
{
|
|
||||||
//printf("ICMP6!\n");
|
|
||||||
ICMP6Flag = 1;
|
|
||||||
|
|
||||||
switch (type) //Add new ICMP6 functions here, you can also use codes to narrow the area of single functions.
|
|
||||||
{
|
|
||||||
//All the echo stuff here
|
|
||||||
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:
|
|
||||||
Context(t, icmpp, len, caplen, data, ip_hdr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
//All router related stuff should eventually be handled by the Router()
|
|
||||||
case ND_REDIRECT:
|
|
||||||
case ND_ROUTER_SOLICIT:
|
|
||||||
case ICMP6_ROUTER_RENUMBERING:
|
|
||||||
case ND_ROUTER_ADVERT:
|
|
||||||
Router(t, icmpp, len, caplen, data, ip_hdr); //currently only logs the router stuff for other than router_advert
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* listed for convenience
|
|
||||||
case ICMP6_PARAM_PROB: break;
|
|
||||||
case MLD_LISTENER_QUERY: break;
|
|
||||||
case MLD_LISTENER_REPORT: break;
|
|
||||||
case MLD_LISTENER_REDUCTION: break;
|
|
||||||
case ND_NEIGHBOR_SOLICIT: break;
|
|
||||||
case ND_NEIGHBOR_ADVERT: break;
|
|
||||||
case ND_REDIRECT: break;
|
|
||||||
case ICMP6_ROUTER_RENUMBERING: break;
|
|
||||||
case ND_NEIGHBOR_SOLICIT: break;
|
|
||||||
case ND_NEIGHBOR_ADVERT: break;
|
|
||||||
case ICMP6_TIME_EXCEEDED: break;
|
|
||||||
*/
|
|
||||||
|
|
||||||
default: ICMPEvent(icmp_sent, ICMP6Flag); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( ip_hdr->NextProto() == IPPROTO_ICMP )
|
|
||||||
{
|
|
||||||
|
|
||||||
switch (type) //Add new ICMP4 functions here
|
|
||||||
{
|
{
|
||||||
case ICMP_ECHO:
|
case ICMP_ECHO:
|
||||||
case ICMP_ECHOREPLY:
|
case ICMP_ECHOREPLY:
|
||||||
|
@ -186,36 +117,76 @@ void ICMP_Analyzer::NextICMP(double t , const struct icmp* icmpp , int len , i
|
||||||
|
|
||||||
case ICMP_UNREACH:
|
case ICMP_UNREACH:
|
||||||
case ICMP_TIMXCEED:
|
case ICMP_TIMXCEED:
|
||||||
Context(t, icmpp, len, caplen, data, ip_hdr);
|
Context4(t, icmpp, len, caplen, data, ip_hdr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: ICMPEvent(icmp_sent, ICMP6Flag); break;
|
default:
|
||||||
|
ICMPEvent(icmp_sent, icmpp, len, 0); break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BROv6
|
||||||
|
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:
|
||||||
|
case ND_ROUTER_SOLICIT:
|
||||||
|
case ICMP6_ROUTER_RENUMBERING:
|
||||||
|
case ND_ROUTER_ADVERT:
|
||||||
|
Router(t, icmpp, len, caplen, data, ip_hdr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Currently not specifically implemented.
|
||||||
|
case ICMP6_PARAM_PROB:
|
||||||
|
case MLD_LISTENER_QUERY:
|
||||||
|
case MLD_LISTENER_REPORT:
|
||||||
|
case MLD_LISTENER_REDUCTION:
|
||||||
|
case ND_NEIGHBOR_SOLICIT:
|
||||||
|
case ND_NEIGHBOR_ADVERT:
|
||||||
|
case ND_REDIRECT:
|
||||||
|
case ICMP6_ROUTER_RENUMBERING:
|
||||||
|
case ND_NEIGHBOR_SOLICIT:
|
||||||
|
case ND_NEIGHBOR_ADVERT:
|
||||||
|
case ICMP6_TIME_EXCEEDED:
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ICMPEvent(icmp_sent, icmpp, len, 1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
Weird("Malformed ip header");
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void ICMP_Analyzer::ICMPEvent(EventHandlerPtr f, const struct icmp* icmpp, int len, int icmpv6)
|
||||||
void ICMP_Analyzer::ICMPEvent(EventHandlerPtr f, int ICMP6Flag)
|
|
||||||
{
|
{
|
||||||
if ( ! f )
|
if ( ! f )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
val_list* vl = new val_list;
|
val_list* vl = new val_list;
|
||||||
vl->append(BuildConnVal());
|
vl->append(BuildConnVal());
|
||||||
vl->append(BuildICMPVal(ICMP6Flag));
|
vl->append(BuildICMPVal(icmpp, len, icmpv6));
|
||||||
//if ( f == icmp_sent ) //for now, testing purposes
|
|
||||||
vl->append(new Val(ICMP6Flag, TYPE_BOOL));
|
|
||||||
|
|
||||||
ConnectionEvent(f, vl);
|
ConnectionEvent(f, vl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RecordVal* ICMP_Analyzer::BuildICMPVal(const struct icmp* icmpp, int len, int icmpv6)
|
||||||
RecordVal* ICMP_Analyzer::BuildICMPVal(int ICMP6Flag)
|
|
||||||
{
|
{
|
||||||
if ( ! icmp_conn_val )
|
if ( ! icmp_conn_val )
|
||||||
{
|
{
|
||||||
|
@ -223,15 +194,10 @@ RecordVal* ICMP_Analyzer::BuildICMPVal(int ICMP6Flag)
|
||||||
|
|
||||||
icmp_conn_val->Assign(0, new AddrVal(Conn()->OrigAddr()));
|
icmp_conn_val->Assign(0, new AddrVal(Conn()->OrigAddr()));
|
||||||
icmp_conn_val->Assign(1, new AddrVal(Conn()->RespAddr()));
|
icmp_conn_val->Assign(1, new AddrVal(Conn()->RespAddr()));
|
||||||
|
icmp_conn_val->Assign(2, new Val(icmpp->icmp_type, TYPE_COUNT));
|
||||||
if ( ICMP6Flag == 1 )
|
icmp_conn_val->Assign(3, new Val(icmpp->icmp_code, TYPE_COUNT));
|
||||||
icmp_conn_val->Assign(2, new Val(Type6to4(type), TYPE_COUNT)); //to avoid errors in getting the message type *name* right on the scripting level, type number will be different from true ipv6
|
|
||||||
else
|
|
||||||
icmp_conn_val->Assign(2, new Val(type, TYPE_COUNT));
|
|
||||||
|
|
||||||
|
|
||||||
icmp_conn_val->Assign(3, new Val(code, TYPE_COUNT));
|
|
||||||
icmp_conn_val->Assign(4, new Val(len, TYPE_COUNT));
|
icmp_conn_val->Assign(4, new Val(len, TYPE_COUNT));
|
||||||
|
icmp_conn_val->Assign(5, new Val(icmpv6, TYPE_BOOL));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref(icmp_conn_val);
|
Ref(icmp_conn_val);
|
||||||
|
@ -239,15 +205,74 @@ RecordVal* ICMP_Analyzer::BuildICMPVal(int ICMP6Flag)
|
||||||
return icmp_conn_val;
|
return icmp_conn_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TransportProto ICMP_Analyzer::GetContextProtocol(const IP_Hdr* ip_hdr, uint32* src_port, uint32* dst_port)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
transport_hdr = ((u_char *) ip_hdr->IP6_Hdr() + ip_hdr_len);
|
||||||
|
|
||||||
|
TransportProto proto;
|
||||||
|
|
||||||
|
switch ( ip_hdr->NextProto() ) {
|
||||||
|
case 1: proto = TRANSPORT_ICMP; break;
|
||||||
|
case 6: proto = TRANSPORT_TCP; break;
|
||||||
|
case 17: proto = TRANSPORT_UDP; break;
|
||||||
|
case 58: proto = TRANSPORT_ICMP; //TransportProto Hack // XXX What's this?
|
||||||
|
default: proto = TRANSPORT_UNKNOWN; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( proto ) {
|
||||||
|
case TRANSPORT_ICMP:
|
||||||
|
{
|
||||||
|
const struct icmp* icmpp =
|
||||||
|
(const struct icmp *) transport_hdr;
|
||||||
|
bool is_one_way; // dummy
|
||||||
|
*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);
|
||||||
|
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);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
*src_port = *dst_port = ntohs(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return proto;
|
||||||
|
}
|
||||||
|
|
||||||
RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data)
|
RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data)
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* For use only with ICMP4, ICMPV6 context extraction is still non-functional
|
|
||||||
*/
|
|
||||||
|
|
||||||
const IP_Hdr ip_hdr_data((const struct ip*) data);
|
const IP_Hdr ip_hdr_data((const struct ip*) data);
|
||||||
const IP_Hdr* ip_hdr = &ip_hdr_data;
|
const IP_Hdr* ip_hdr = &ip_hdr_data;
|
||||||
int ICMP6Flag = 0;
|
|
||||||
|
|
||||||
uint32 ip_hdr_len = ip_hdr->HdrLen();
|
uint32 ip_hdr_len = ip_hdr->HdrLen();
|
||||||
|
|
||||||
|
@ -258,7 +283,8 @@ RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data)
|
||||||
uint32 src_port, dst_port;
|
uint32 src_port, dst_port;
|
||||||
|
|
||||||
if ( ip_hdr_len < sizeof(struct ip) || ip_hdr_len > uint32(len) )
|
if ( ip_hdr_len < sizeof(struct ip) || ip_hdr_len > uint32(len) )
|
||||||
{ // We don't have an entire IP header.
|
{
|
||||||
|
// We don't have an entire IP header.
|
||||||
bad_hdr_len = 1;
|
bad_hdr_len = 1;
|
||||||
ip_len = frag_offset = 0;
|
ip_len = frag_offset = 0;
|
||||||
DF = MF = bad_checksum = 0;
|
DF = MF = bad_checksum = 0;
|
||||||
|
@ -275,62 +301,19 @@ RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data)
|
||||||
src_addr = ip_hdr->SrcAddr4();
|
src_addr = ip_hdr->SrcAddr4();
|
||||||
dst_addr = ip_hdr->DstAddr4();
|
dst_addr = ip_hdr->DstAddr4();
|
||||||
|
|
||||||
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 = ip_hdr->FragField();
|
uint32 frag_field = ip_hdr->FragField();
|
||||||
DF = ip_hdr->DF();
|
DF = ip_hdr->DF();
|
||||||
MF = frag_field & 0x2000;
|
MF = frag_field & 0x2000;
|
||||||
frag_offset = frag_field & /* IP_OFFMASK not portable */ 0x1fff;
|
frag_offset = frag_field & /* IP_OFFMASK not portable */ 0x1fff;
|
||||||
|
|
||||||
const u_char* transport_hdr = ((u_char *) ip_hdr->IP4_Hdr() + ip_hdr_len);
|
if ( uint32(len) >= ip_hdr_len + 4 )
|
||||||
|
proto = GetContextProtocol(ip_hdr, &src_port, &dst_port);
|
||||||
if ( uint32(len) < ip_hdr_len + 4 ) //what is this value for ipv6?
|
else
|
||||||
{
|
{
|
||||||
// 4 above is the magic number meaning that both
|
// 4 above is the magic number meaning that both
|
||||||
// port numbers are included in the ICMP.
|
// port numbers are included in the ICMP.
|
||||||
bad_hdr_len = 1;
|
|
||||||
src_port = dst_port = 0;
|
src_port = dst_port = 0;
|
||||||
}
|
bad_hdr_len = 1;
|
||||||
|
|
||||||
switch ( proto ) {
|
|
||||||
case TRANSPORT_ICMP:
|
|
||||||
{
|
|
||||||
const struct icmp* icmpp =
|
|
||||||
(const struct icmp *) transport_hdr;
|
|
||||||
bool is_one_way; // dummy
|
|
||||||
src_port = ntohs(icmpp->icmp_type);
|
|
||||||
dst_port = ntohs(ICMP4_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);
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
src_port = dst_port = ntohs(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,48 +324,40 @@ RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data)
|
||||||
id_val->Assign(1, new PortVal(src_port, proto));
|
id_val->Assign(1, new PortVal(src_port, proto));
|
||||||
id_val->Assign(2, new AddrVal(dst_addr));
|
id_val->Assign(2, new AddrVal(dst_addr));
|
||||||
id_val->Assign(3, new PortVal(dst_port, proto));
|
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(1, new Val(ip_len, TYPE_COUNT));
|
||||||
iprec->Assign(2, new Val(proto, TYPE_COUNT));
|
iprec->Assign(2, new Val(proto, TYPE_COUNT));
|
||||||
iprec->Assign(3, new Val(frag_offset, TYPE_COUNT));
|
iprec->Assign(3, new Val(bad_hdr_len, TYPE_BOOL));
|
||||||
iprec->Assign(4, new Val(bad_hdr_len, TYPE_BOOL));
|
iprec->Assign(4, new Val(bad_checksum, TYPE_BOOL));
|
||||||
iprec->Assign(5, new Val(bad_checksum, TYPE_BOOL));
|
iprec->Assign(5, new Val(frag_offset, TYPE_COUNT));
|
||||||
iprec->Assign(6, new Val(MF, TYPE_BOOL));
|
iprec->Assign(6, new Val(MF, TYPE_BOOL));
|
||||||
iprec->Assign(7, new Val(DF, TYPE_BOOL));
|
iprec->Assign(7, new Val(DF, TYPE_BOOL));
|
||||||
iprec->Assign(8, new Val(ICMP6Flag, TYPE_BOOL));
|
|
||||||
|
|
||||||
return iprec;
|
return iprec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data)
|
RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data)
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* For use with ICMP6 error message context extraction (possibly very frail function)
|
|
||||||
*/
|
|
||||||
|
|
||||||
const IP_Hdr ip_hdr_data((const struct ip6_hdr*) data);
|
const IP_Hdr ip_hdr_data((const struct ip6_hdr*) data);
|
||||||
const IP_Hdr* ip_hdr = &ip_hdr_data;
|
const IP_Hdr* ip_hdr = &ip_hdr_data;
|
||||||
int ICMP6Flag = 1;
|
|
||||||
int DF = 0, MF = 0, bad_hdr_len = 0, bad_checksum = 0;
|
int DF = 0, MF = 0, bad_hdr_len = 0, bad_checksum = 0;
|
||||||
|
TransportProto proto = TRANSPORT_UNKNOWN;
|
||||||
|
|
||||||
uint32 ip_hdr_len = ip_hdr->HdrLen(); //should always be 40
|
uint32 ip_hdr_len = ip_hdr->HdrLen(); //should always be 40
|
||||||
uint32* src_addr;
|
uint32* src_addr;
|
||||||
uint32* dst_addr;
|
uint32* dst_addr;
|
||||||
uint32 ip_len, frag_offset = 0;
|
uint32 ip_len, frag_offset = 0;
|
||||||
TransportProto proto = TRANSPORT_UNKNOWN;
|
|
||||||
uint32 src_port, dst_port;
|
uint32 src_port, dst_port;
|
||||||
|
|
||||||
if ( ip_hdr_len < sizeof(struct ip6_hdr) || ip_hdr_len != 40 )
|
if ( ip_hdr_len < sizeof(struct ip6_hdr) || ip_hdr_len != 40 ) // XXX What's the 2nd part doing?
|
||||||
{
|
{
|
||||||
bad_hdr_len = 1;
|
bad_hdr_len = 1;
|
||||||
ip_len = 0;
|
ip_len = 0;
|
||||||
src_addr = dst_addr = 0;
|
src_addr = dst_addr = 0;
|
||||||
src_port = dst_port = 0;
|
src_port = dst_port = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ip_len = ip_hdr->TotalLen();
|
ip_len = ip_hdr->TotalLen();
|
||||||
|
@ -390,61 +365,14 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data)
|
||||||
src_addr = (uint32 *) ip_hdr->SrcAddr();
|
src_addr = (uint32 *) ip_hdr->SrcAddr();
|
||||||
dst_addr = (uint32 *) ip_hdr->DstAddr();
|
dst_addr = (uint32 *) ip_hdr->DstAddr();
|
||||||
|
|
||||||
|
if ( uint32(len) >= ip_hdr_len + 4 )
|
||||||
|
proto = GetContextProtocol(ip_hdr, &src_port, &dst_port);
|
||||||
switch ( ip_hdr->NextProto() ) {
|
else
|
||||||
case 1: proto = TRANSPORT_ICMP; break;
|
|
||||||
case 6: proto = TRANSPORT_TCP; break;
|
|
||||||
case 17: proto = TRANSPORT_UDP; break;
|
|
||||||
case 58: proto = TRANSPORT_ICMP; break; //TransportProto Hack
|
|
||||||
|
|
||||||
// Default uses TRANSPORT_UNKNOWN, per initialization above.
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const u_char* transport_hdr = ((u_char *)ip_hdr->IP6_Hdr() + ip_hdr_len);
|
|
||||||
|
|
||||||
if ( uint32(len) < ip_hdr_len + 4 )
|
|
||||||
{
|
{
|
||||||
// 4 above is the magic number meaning that both
|
// 4 above is the magic number meaning that both
|
||||||
// port numbers are included in the ICMP.
|
// port numbers are included in the ICMP.
|
||||||
bad_hdr_len = 1;
|
|
||||||
src_port = dst_port = 0;
|
src_port = dst_port = 0;
|
||||||
}
|
bad_hdr_len = 1;
|
||||||
|
|
||||||
switch ( proto ) {
|
|
||||||
case TRANSPORT_ICMP:
|
|
||||||
{
|
|
||||||
const struct icmp* icmpp =
|
|
||||||
(const struct icmp *) transport_hdr;
|
|
||||||
bool is_one_way; // dummy
|
|
||||||
src_port = ntohs(icmpp->icmp_type);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
src_port = dst_port = ntohs(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,7 +387,7 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data)
|
||||||
iprec->Assign(0, id_val);
|
iprec->Assign(0, id_val);
|
||||||
iprec->Assign(1, new Val(ip_len, TYPE_COUNT));
|
iprec->Assign(1, new Val(ip_len, TYPE_COUNT));
|
||||||
|
|
||||||
//TransportProto Hack
|
//TransportProto Hack // XXX Likewise.
|
||||||
if ( ip_hdr->NextProto() == 58 || 17 ) //if the encap packet is ICMPv6 we force this... (cause there is no IGMP (by that name) for ICMPv6), rather ugly hack once more
|
if ( ip_hdr->NextProto() == 58 || 17 ) //if the encap packet is ICMPv6 we force this... (cause there is no IGMP (by that name) for ICMPv6), rather ugly hack once more
|
||||||
{
|
{
|
||||||
iprec->Assign(2, new Val(58, TYPE_COUNT));
|
iprec->Assign(2, new Val(58, TYPE_COUNT));
|
||||||
|
@ -469,28 +397,18 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data)
|
||||||
iprec->Assign(2, new Val(proto, TYPE_COUNT));
|
iprec->Assign(2, new Val(proto, TYPE_COUNT));
|
||||||
}
|
}
|
||||||
|
|
||||||
iprec->Assign(3, new Val(frag_offset, TYPE_COUNT)); //NA for ip6
|
iprec->Assign(3, new Val(bad_hdr_len, TYPE_BOOL));
|
||||||
iprec->Assign(4, new Val(bad_hdr_len, TYPE_BOOL));
|
|
||||||
iprec->Assign(5, new Val(bad_checksum, TYPE_BOOL));
|
// The following are not available for IPv6.
|
||||||
iprec->Assign(6, new Val(MF, TYPE_BOOL)); //NA for ip6
|
iprec->Assign(4, new Val(0, TYPE_BOOL)); // bad_checksum
|
||||||
iprec->Assign(7, new Val(DF, TYPE_BOOL)); //NA for ip6
|
iprec->Assign(5, new Val(frag_offset, TYPE_COUNT)); // frag_offset
|
||||||
iprec->Assign(8, new Val(ICMP6Flag, TYPE_BOOL)); //ICMP6Flag
|
iprec->Assign(6, new Val(0, TYPE_BOOL)); // MF
|
||||||
|
iprec->Assign(7, new Val(1, TYPE_BOOL)); // DF
|
||||||
|
|
||||||
return iprec;
|
return iprec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool ICMP_Analyzer::IsReuse(double /* t */, const u_char* /* pkt */)
|
bool ICMP_Analyzer::IsReuse(double /* t */, const u_char* /* pkt */)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -504,10 +422,12 @@ void ICMP_Analyzer::Describe(ODesc* d) const
|
||||||
d->AddSP(")");
|
d->AddSP(")");
|
||||||
|
|
||||||
d->Add(dotted_addr(Conn()->OrigAddr()));
|
d->Add(dotted_addr(Conn()->OrigAddr()));
|
||||||
|
#if 0
|
||||||
d->Add(".");
|
d->Add(".");
|
||||||
d->Add(type);
|
d->Add(type);
|
||||||
d->Add(".");
|
d->Add(".");
|
||||||
d->Add(code);
|
d->Add(code);
|
||||||
|
#endif
|
||||||
|
|
||||||
d->SP();
|
d->SP();
|
||||||
d->AddSP("->");
|
d->AddSP("->");
|
||||||
|
@ -543,19 +463,16 @@ unsigned int ICMP_Analyzer::MemoryAllocation() const
|
||||||
|
|
||||||
void ICMP_Analyzer::Echo(double t, const struct icmp* icmpp, int len,
|
void ICMP_Analyzer::Echo(double t, const struct icmp* icmpp, int len,
|
||||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||||
{ //For handling all Echo related ICMP messages
|
|
||||||
EventHandlerPtr f = 0;
|
|
||||||
int ICMP6Flag = 0;
|
|
||||||
|
|
||||||
//printf("Executing: Echo, NextProto:%d\n",ip_hdr->NextProto());
|
|
||||||
|
|
||||||
if ( ip_hdr->NextProto() == IPPROTO_ICMPV6 )
|
|
||||||
{
|
{
|
||||||
f = type == ICMP6_ECHO_REQUEST ? icmp_echo_request : icmp_echo_reply;
|
// For handling all Echo related ICMP messages
|
||||||
ICMP6Flag = 1;
|
EventHandlerPtr f = 0;
|
||||||
}
|
|
||||||
|
#ifdef BROv6
|
||||||
|
if ( ip_hdr->NextProto() == IPPROTO_ICMPV6 )
|
||||||
|
f = (icmpp->icmp_type == ICMP6_ECHO_REQUEST) ? icmp_echo_request : icmp_echo_reply;
|
||||||
else
|
else
|
||||||
f = type == ICMP_ECHO ? icmp_echo_request : icmp_echo_reply;
|
#endif
|
||||||
|
f = (icmpp->icmp_type == ICMP_ECHO) ? icmp_echo_request : icmp_echo_reply;
|
||||||
|
|
||||||
if ( ! f )
|
if ( ! f )
|
||||||
return;
|
return;
|
||||||
|
@ -563,137 +480,110 @@ void ICMP_Analyzer::Echo(double t, const struct icmp* icmpp, int len,
|
||||||
int iid = ntohs(icmpp->icmp_hun.ih_idseq.icd_id);
|
int iid = ntohs(icmpp->icmp_hun.ih_idseq.icd_id);
|
||||||
int iseq = ntohs(icmpp->icmp_hun.ih_idseq.icd_seq);
|
int iseq = ntohs(icmpp->icmp_hun.ih_idseq.icd_seq);
|
||||||
|
|
||||||
//printf("Check these values: iid:[%d] iseq:[%d]\n",iid,iseq);
|
|
||||||
|
|
||||||
BroString* payload = new BroString(data, caplen, 0);
|
BroString* payload = new BroString(data, caplen, 0);
|
||||||
|
|
||||||
val_list* vl = new val_list;
|
val_list* vl = new val_list;
|
||||||
vl->append(BuildConnVal());
|
vl->append(BuildConnVal());
|
||||||
vl->append(BuildICMPVal(ICMP6Flag));
|
vl->append(BuildICMPVal(icmpp, len, ip_hdr->NextProto() != IPPROTO_ICMP));
|
||||||
vl->append(new Val(iid, TYPE_COUNT));
|
vl->append(new Val(iid, TYPE_COUNT));
|
||||||
vl->append(new Val(iseq, TYPE_COUNT));
|
vl->append(new Val(iseq, TYPE_COUNT));
|
||||||
vl->append(new StringVal(payload));
|
vl->append(new StringVal(payload));
|
||||||
vl->append(new Val(ICMP6Flag, TYPE_BOOL));
|
|
||||||
|
|
||||||
ConnectionEvent(f, vl);
|
ConnectionEvent(f, vl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ICMP_Analyzer::Router(double t, const struct icmp* icmpp, int len,
|
void ICMP_Analyzer::Router(double t, const struct icmp* icmpp, int len,
|
||||||
int caplen, const u_char*& data, const IP_Hdr* /*ip_hdr*/)
|
int caplen, const u_char*& data, const IP_Hdr* /*ip_hdr*/)
|
||||||
//For handling router related ICMP messages,
|
|
||||||
{
|
{
|
||||||
EventHandlerPtr f = 0;
|
EventHandlerPtr f = 0;
|
||||||
int ICMP6Flag = 1;
|
|
||||||
|
|
||||||
switch ( type )
|
switch ( icmpp->icmp_type )
|
||||||
{
|
{
|
||||||
case ND_ROUTER_ADVERT: f = icmp_router_advertisement; break;
|
case ND_ROUTER_ADVERT:
|
||||||
|
f = icmp_router_advertisement;
|
||||||
|
break;
|
||||||
|
|
||||||
case ND_REDIRECT:
|
case ND_REDIRECT:
|
||||||
case ND_ROUTER_SOLICIT:
|
case ND_ROUTER_SOLICIT:
|
||||||
case ICMP6_ROUTER_RENUMBERING:
|
case ICMP6_ROUTER_RENUMBERING:
|
||||||
default: ICMPEvent(icmp_sent,ICMP6Flag); return;
|
default:
|
||||||
|
ICMPEvent(icmp_sent, icmpp, len, 1);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
val_list* vl = new val_list;
|
val_list* vl = new val_list;
|
||||||
vl->append(BuildConnVal());
|
vl->append(BuildConnVal());
|
||||||
vl->append(BuildICMPVal(ICMP6Flag));
|
vl->append(BuildICMPVal(icmpp, len, 1));
|
||||||
vl->append(new Val(ICMP6Flag, TYPE_BOOL));
|
|
||||||
|
|
||||||
ConnectionEvent(f, vl);
|
ConnectionEvent(f, vl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ICMP_Analyzer::Context4(double t, const struct icmp* icmpp,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ICMP_Analyzer::Context(double t, const struct icmp* icmpp,
|
|
||||||
int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||||
{//For handling the ICMP error messages
|
{
|
||||||
|
|
||||||
EventHandlerPtr f = 0;
|
EventHandlerPtr f = 0;
|
||||||
int ICMP6Flag = 0;
|
|
||||||
|
|
||||||
|
switch ( icmpp->icmp_type )
|
||||||
if ( ip_hdr->NextProto() == IPPROTO_ICMPV6 ) //is ip6
|
|
||||||
{
|
{
|
||||||
|
case ICMP_UNREACH:
|
||||||
|
f = icmp_unreachable;
|
||||||
|
break;
|
||||||
|
|
||||||
ICMP6Flag = 1;
|
case ICMP_TIMXCEED:
|
||||||
//printf("Executing: Context for ICMPv6\n");
|
f = icmp_error_message;
|
||||||
|
break;
|
||||||
switch ( type )
|
|
||||||
{
|
|
||||||
case ICMP6_DST_UNREACH: f = icmp_unreachable; break;
|
|
||||||
case ICMP6_PARAM_PROB: f = icmp_error_message; break;
|
|
||||||
case ICMP6_TIME_EXCEEDED: f = icmp_error_message; break;
|
|
||||||
case ICMP6_PACKET_TOO_BIG: f = icmp_error_message; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( f )
|
|
||||||
{
|
|
||||||
val_list* vl = new val_list;
|
|
||||||
vl->append(BuildConnVal()); //check for ip6 functionality
|
|
||||||
vl->append(BuildICMPVal(ICMP6Flag)); //check for ip6 functionality
|
|
||||||
vl->append(new Val(code, TYPE_COUNT));
|
|
||||||
vl->append(ExtractICMP6Context(caplen, data));
|
|
||||||
|
|
||||||
ConnectionEvent(f, vl);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else if ( ip_hdr->NextProto() == IPPROTO_ICMP )
|
|
||||||
{
|
|
||||||
//printf("Executing: Context for ICMP\n");
|
|
||||||
switch ( type )
|
|
||||||
{
|
|
||||||
case ICMP_UNREACH: f = icmp_unreachable; break;
|
|
||||||
case ICMP_TIMXCEED: f = icmp_error_message; break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( f )
|
if ( f )
|
||||||
{
|
{
|
||||||
val_list* vl = new val_list;
|
val_list* vl = new val_list;
|
||||||
vl->append(BuildConnVal());
|
vl->append(BuildConnVal());
|
||||||
vl->append(BuildICMPVal(ICMP6Flag));
|
vl->append(BuildICMPVal(icmpp, len, 0));
|
||||||
vl->append(new Val(code, TYPE_COUNT));
|
vl->append(new Val(icmpp->icmp_code, TYPE_COUNT));
|
||||||
vl->append(ExtractICMP4Context(caplen, data));
|
vl->append(ExtractICMP4Context(caplen, data));
|
||||||
|
|
||||||
|
|
||||||
ConnectionEvent(f, vl);
|
ConnectionEvent(f, vl);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
|
||||||
|
#ifdef BROv6
|
||||||
|
void ICMP_Analyzer::Context6(double t, const struct icmp* icmpp,
|
||||||
|
int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
|
||||||
{
|
{
|
||||||
Weird("ICMP packet, invalid data\n"); //make this more descriptive
|
EventHandlerPtr f = 0;
|
||||||
}
|
|
||||||
|
switch ( icmpp->icmp_type )
|
||||||
|
{
|
||||||
|
case ICMP6_DST_UNREACH:
|
||||||
|
f = icmp_unreachable;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ICMP6_PARAM_PROB:
|
||||||
|
case ICMP6_TIME_EXCEEDED:
|
||||||
|
case ICMP6_PACKET_TOO_BIG:
|
||||||
|
f = icmp_error_message;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( f )
|
||||||
|
{
|
||||||
|
val_list* vl = new val_list;
|
||||||
|
vl->append(BuildConnVal());
|
||||||
|
vl->append(BuildICMPVal(icmpp, len, 1));
|
||||||
|
vl->append(new Val(icmpp->icmp_code, TYPE_COUNT));
|
||||||
|
vl->append(ExtractICMP6Context(caplen, data));
|
||||||
|
ConnectionEvent(f, vl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way)
|
int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way)
|
||||||
{
|
{
|
||||||
is_one_way = false;
|
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.
|
// to track corresponding ICMP requests/replies.
|
||||||
// Note that for the two-way ICMP messages, icmp_code is
|
// Note that for the two-way ICMP messages, icmp_code is
|
||||||
// always 0 (RFC 792).
|
// always 0 (RFC 792).
|
||||||
|
@ -720,12 +610,7 @@ int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way)
|
||||||
{
|
{
|
||||||
is_one_way = false;
|
is_one_way = false;
|
||||||
|
|
||||||
/**ICMP6 version of the ICMP4_counterpart, under work**/
|
|
||||||
//not yet used anywhere, for the context class
|
|
||||||
|
|
||||||
switch ( icmp_type ) {
|
switch ( icmp_type ) {
|
||||||
|
|
||||||
|
|
||||||
case ICMP6_ECHO_REQUEST: return ICMP6_ECHO_REPLY;
|
case ICMP6_ECHO_REQUEST: return ICMP6_ECHO_REPLY;
|
||||||
case ICMP6_ECHO_REPLY: return ICMP6_ECHO_REQUEST;
|
case ICMP6_ECHO_REPLY: return ICMP6_ECHO_REQUEST;
|
||||||
|
|
||||||
|
@ -738,39 +623,17 @@ int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way)
|
||||||
case MLD_LISTENER_QUERY: return MLD_LISTENER_REPORT;
|
case MLD_LISTENER_QUERY: return MLD_LISTENER_REPORT;
|
||||||
case MLD_LISTENER_REPORT: return MLD_LISTENER_QUERY;
|
case MLD_LISTENER_REPORT: return MLD_LISTENER_QUERY;
|
||||||
|
|
||||||
case 139: return 140; //ICMP node information query and response respectively (not defined in icmp6.h)
|
// ICMP node information query and response respectively (not defined in
|
||||||
|
// icmp6.h)
|
||||||
|
case 139: return 140;
|
||||||
case 140: return 139;
|
case 140: return 139;
|
||||||
|
|
||||||
case 144: return 145; //Home Agent Address Discovery Request Message and reply
|
// Home Agent Address Discovery Request Message and reply
|
||||||
|
case 144: return 145;
|
||||||
case 145: return 144;
|
case 145: return 144;
|
||||||
|
|
||||||
//check the rest of the counterparts
|
// TODO: Add further counterparts.
|
||||||
|
|
||||||
default: is_one_way = true; return icmp_code;
|
default: is_one_way = true; return icmp_code;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//For mapping ICMP types and codes of v6 to v4. Because we are using same events for both icmpv4 and icmpv6 there is some overlap
|
|
||||||
//in ICMP types. If this function is used, the name (checked from a table in the scripts) will be incorrect for the listed
|
|
||||||
//types, but the names will be correct for all ICMP types.
|
|
||||||
int Type6to4(int icmp_type)
|
|
||||||
{
|
|
||||||
switch ( icmp_type ) //For these three values, the type number will be wrong if this is used!
|
|
||||||
{ //easy way to disable this is just to comment all the cases out, and leave only the default.
|
|
||||||
case ICMP6_DST_UNREACH: return ICMP_UNREACH; break;
|
|
||||||
case ICMP6_TIME_EXCEEDED: return ICMP_TIMXCEED; break;
|
|
||||||
case ICMP6_PARAM_PROB: return ICMP_PARAMPROB; break;
|
|
||||||
|
|
||||||
default: return icmp_type; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int Code6to4(int icmp_code) //not used yet for anything
|
|
||||||
{
|
|
||||||
switch ( icmp_code )
|
|
||||||
{
|
|
||||||
default: return icmp_code; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
43
src/ICMP.h
43
src/ICMP.h
|
@ -34,7 +34,7 @@ protected:
|
||||||
virtual bool IsReuse(double t, const u_char* pkt);
|
virtual bool IsReuse(double t, const u_char* pkt);
|
||||||
virtual unsigned int MemoryAllocation() const;
|
virtual unsigned int MemoryAllocation() const;
|
||||||
|
|
||||||
void ICMPEvent(EventHandlerPtr f, int ICMP6Flag);
|
void ICMPEvent(EventHandlerPtr f, const struct icmp* icmpp, int len, int icmpv6);
|
||||||
|
|
||||||
void Echo(double t, const struct icmp* icmpp, int len,
|
void Echo(double t, const struct icmp* icmpp, int len,
|
||||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
|
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
|
||||||
|
@ -43,47 +43,40 @@ protected:
|
||||||
void Router(double t, const struct icmp* icmpp, int len,
|
void Router(double t, const struct icmp* icmpp, int len,
|
||||||
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
|
int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Describe(ODesc* d) const;
|
void Describe(ODesc* d) const;
|
||||||
|
|
||||||
RecordVal* BuildICMPVal(int ICMP6Flag);
|
RecordVal* BuildICMPVal(const struct icmp* icmpp, int len, int icmpv6);
|
||||||
|
|
||||||
virtual void NextICMP(double t, const struct icmp* icmpp,
|
void NextICMP4(double t, const struct icmp* icmpp, int len, int caplen,
|
||||||
int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr);
|
const u_char*& data, const IP_Hdr* ip_hdr );
|
||||||
|
|
||||||
RecordVal* ExtractICMP4Context(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);
|
||||||
|
|
||||||
|
#ifdef BROv6
|
||||||
|
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);
|
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);
|
||||||
|
#endif
|
||||||
|
|
||||||
RecordVal* icmp_conn_val;
|
RecordVal* icmp_conn_val;
|
||||||
int type;
|
|
||||||
int code;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
int request_len, reply_len;
|
int request_len, reply_len;
|
||||||
|
|
||||||
RuleMatcherState matcher_state;
|
RuleMatcherState matcher_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*class ICMP4_Analyzer : public ICMP_Analyzer {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class ICMP6_Analyzer : public ICMP_Analyzer {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};*/
|
|
||||||
|
|
||||||
// Returns the counterpart type to the given type (e.g., the counterpart
|
// Returns the counterpart type to the given type (e.g., the counterpart
|
||||||
// to ICMP_ECHOREPLY is ICMP_ECHO).
|
// 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 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);
|
extern int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way);
|
||||||
extern int Type6to4(int icmp_type);
|
|
||||||
extern int Code6to4(int icmp_code);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -53,12 +53,12 @@ event udp_reply%(u: connection%);
|
||||||
event udp_contents%(u: connection, is_orig: bool, contents: string%);
|
event udp_contents%(u: connection, is_orig: bool, contents: string%);
|
||||||
event udp_session_done%(u: connection%);
|
event udp_session_done%(u: connection%);
|
||||||
|
|
||||||
event icmp_sent%(c: connection, icmp: icmp_conn, ICMP6: bool%);
|
event icmp_sent%(c: connection, icmp: icmp_conn%);
|
||||||
event icmp_echo_request%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string, ICMP6: bool%);
|
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, ICMP6: bool%);
|
event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%);
|
||||||
event icmp_unreachable%(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_error_message%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%);
|
event icmp_error_message%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%);
|
||||||
event icmp_router_advertisement%(c: connection, icmp: icmp_conn, ICMP6: bool%);
|
event icmp_router_advertisement%(c: connection, icmp: icmp_conn%);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -86,14 +86,8 @@ int udp_checksum(const struct ip* ip, const struct udphdr* up, int len)
|
||||||
#ifdef BROv6
|
#ifdef BROv6
|
||||||
int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len)
|
int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len)
|
||||||
{
|
{
|
||||||
/**From RFC for udp4 (same for udp6, except for different pseudoheader which is same as for icmp6)
|
// UDP over IPv6 uses the same checksum function as over IPv4 but a
|
||||||
Computed as the 16-bit one's complement of the one's complement sum of a
|
// different pseuod-header over which it is computed.
|
||||||
pseudo header of information from the IP header, the UDP header, and the
|
|
||||||
data, padded as needed with zero bytes at the end to make a multiple of
|
|
||||||
two bytes. If the checksum is cleared to zero, then checksuming is
|
|
||||||
disabled. If the computed checksum is zero, then this field must be set
|
|
||||||
to 0xFFFF.
|
|
||||||
**/
|
|
||||||
uint32 sum;
|
uint32 sum;
|
||||||
|
|
||||||
if ( len % 2 == 1 )
|
if ( len % 2 == 1 )
|
||||||
|
@ -108,23 +102,18 @@ int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len)
|
||||||
uint32 l = htonl(len);
|
uint32 l = htonl(len);
|
||||||
sum = ones_complement_checksum((void*) &l, 4, sum);
|
sum = ones_complement_checksum((void*) &l, 4, sum);
|
||||||
uint32 addl_pseudo = htons(IPPROTO_UDP);
|
uint32 addl_pseudo = htons(IPPROTO_UDP);
|
||||||
|
|
||||||
sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum);
|
sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum);
|
||||||
sum = ones_complement_checksum((void*) up, len, sum);
|
sum = ones_complement_checksum((void*) up, len, sum);
|
||||||
|
|
||||||
//printf("checksum, calculated for UDP6: %d\n",sum);
|
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len)
|
int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len)
|
||||||
{
|
{
|
||||||
/**From RFC
|
// ICMP6 uses the same checksum function as over ICMP4 but a different
|
||||||
Checksum that covers the ICMPv6 message. This field contains the 16-bit one's
|
// pseuod-header over which it is computed.
|
||||||
complement of the one's complement sum of the entire ICMPv6 message starting
|
|
||||||
with the ICMPv6 message type field, prepended with a pseudo-header of IPv6
|
|
||||||
header fields.
|
|
||||||
**/
|
|
||||||
uint32 sum;
|
uint32 sum;
|
||||||
|
|
||||||
if ( len % 2 == 1 )
|
if ( len % 2 == 1 )
|
||||||
|
@ -133,19 +122,17 @@ int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len)
|
||||||
else
|
else
|
||||||
sum = 0;
|
sum = 0;
|
||||||
|
|
||||||
//pseudoheader as in udp6 above
|
// Pseudo-header as for UDP over IPv6 above.
|
||||||
sum = ones_complement_checksum((void*) ip6->ip6_src.s6_addr, 16, sum);
|
sum = ones_complement_checksum((void*) ip6->ip6_src.s6_addr, 16, sum);
|
||||||
sum = ones_complement_checksum((void*) ip6->ip6_dst.s6_addr, 16, sum);
|
sum = ones_complement_checksum((void*) ip6->ip6_dst.s6_addr, 16, sum);
|
||||||
uint32 l = htonl(len);
|
uint32 l = htonl(len);
|
||||||
sum = ones_complement_checksum((void*) &l, 4, sum);
|
sum = ones_complement_checksum((void*) &l, 4, sum);
|
||||||
|
|
||||||
uint32 addl_pseudo = htons(IPPROTO_ICMPV6);
|
uint32 addl_pseudo = htons(IPPROTO_ICMPV6);
|
||||||
sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum);
|
sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum);
|
||||||
//pseudoheader complete
|
|
||||||
|
|
||||||
sum = ones_complement_checksum((void*) icmpp, len, sum);
|
sum = ones_complement_checksum((void*) icmpp, len, sum);
|
||||||
|
|
||||||
//printf("checksum, calculated for ICMP6: %d\n",sum);
|
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,12 +140,6 @@ int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len)
|
||||||
|
|
||||||
int icmp_checksum(const struct icmp* icmpp, int len)
|
int icmp_checksum(const struct icmp* icmpp, int len)
|
||||||
{
|
{
|
||||||
/**From RFC
|
|
||||||
Checksum that covers the ICMP message. This is the 16-bit one's
|
|
||||||
complement of the one's complement sum of the ICMP message starting
|
|
||||||
with the Type field. The checksum field should be cleared to zero
|
|
||||||
before generating the checksum.
|
|
||||||
**/
|
|
||||||
uint32 sum;
|
uint32 sum;
|
||||||
if ( len % 2 == 1 )
|
if ( len % 2 == 1 )
|
||||||
// Add in pad byte.
|
// Add in pad byte.
|
||||||
|
@ -168,15 +149,9 @@ int icmp_checksum(const struct icmp* icmpp, int len)
|
||||||
|
|
||||||
sum = ones_complement_checksum((void*) icmpp, len, sum);
|
sum = ones_complement_checksum((void*) icmpp, len, sum);
|
||||||
|
|
||||||
//printf("checksum, calculated for ICMP4: %d\n",sum);
|
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define CLASS_A 0x00000000
|
#define CLASS_A 0x00000000
|
||||||
#define CLASS_B 0x80000000
|
#define CLASS_B 0x80000000
|
||||||
#define CLASS_C 0xc0000000
|
#define CLASS_C 0xc0000000
|
||||||
|
|
|
@ -88,12 +88,14 @@ extern int ones_complement_checksum(const void* p, int b, uint32 sum);
|
||||||
|
|
||||||
extern int tcp_checksum(const struct ip* ip, const struct tcphdr* tp, int len);
|
extern int tcp_checksum(const struct ip* ip, const struct tcphdr* tp, int len);
|
||||||
extern int udp_checksum(const struct ip* ip, const struct udphdr* up, int len);
|
extern int udp_checksum(const struct ip* ip, const struct udphdr* up, int len);
|
||||||
|
extern int icmp_checksum(const struct icmp* icmpp, int len);
|
||||||
|
|
||||||
#ifdef BROv6
|
#ifdef BROv6
|
||||||
extern int udp6_checksum(const struct ip6_hdr* ip, const struct udphdr* up,
|
extern int udp6_checksum(const struct ip6_hdr* ip, const struct udphdr* up,
|
||||||
int len);
|
int len);
|
||||||
extern int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len);
|
extern int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6,
|
||||||
|
int len);
|
||||||
#endif
|
#endif
|
||||||
extern int icmp_checksum(const struct icmp* icmpp, int len);
|
|
||||||
|
|
||||||
// Given an address in host order, returns its "classical network prefix",
|
// Given an address in host order, returns its "classical network prefix",
|
||||||
// also in host order.
|
// also in host order.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue