diff --git a/src/AnalyzerTags.h b/src/AnalyzerTags.h index 42d2f5626c..dc10a55f22 100644 --- a/src/AnalyzerTags.h +++ b/src/AnalyzerTags.h @@ -20,8 +20,7 @@ namespace AnalyzerTag { PIA_TCP, PIA_UDP, // Transport-layer analyzers. - ICMP, - TCP, UDP, + ICMP, TCP, UDP, // Application-layer analyzers (hand-written). BitTorrent, BitTorrentTracker, diff --git a/src/ICMP.cc b/src/ICMP.cc index b2b8f092f1..2fb1a9daab 100644 --- a/src/ICMP.cc +++ b/src/ICMP.cc @@ -52,10 +52,10 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data, assert(caplen >= len); // Should have been caught earlier already. if ( ! ignore_checksums ) - { - int chksum = 0; + { + int chksum = 0; - switch ( ip->NextProto() ) + switch ( ip->NextProto() ) { case IPPROTO_ICMP: chksum = icmp_checksum(icmpp, len); @@ -69,11 +69,11 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data, reporter->InternalError("unexpected IP proto in ICMP analyzer"); } - if ( chksum != 0xffff ) - { - Weird("bad_ICMP6_checksum"); - return; - } + if ( chksum != 0xffff ) + { + Weird("bad_ICMP_checksum"); + return; + } } Conn()->SetLastTime(current_timestamp); @@ -147,6 +147,8 @@ void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int c break; // Router related messages. + case ND_NEIGHBOR_SOLICIT: + case ND_NEIGHBOR_ADVERT: case ND_REDIRECT: case ND_ROUTER_SOLICIT: case ICMP6_ROUTER_RENUMBERING: @@ -156,17 +158,9 @@ void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int c #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); @@ -221,7 +215,7 @@ TransportProto ICMP_Analyzer::GetContextProtocol(const IP_Hdr* ip_hdr, uint32* s 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? + case 58: proto = TRANSPORT_ICMP; break; default: proto = TRANSPORT_UNKNOWN; break; } @@ -386,15 +380,8 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) iprec->Assign(0, id_val); iprec->Assign(1, new Val(ip_len, TYPE_COUNT)); - //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 - { - iprec->Assign(2, new Val(58, TYPE_COUNT)); - } - else - { - iprec->Assign(2, new Val(proto, TYPE_COUNT)); - } + //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(3, new Val(bad_hdr_len, TYPE_BOOL)); @@ -509,12 +496,21 @@ void ICMP_Analyzer::Router(double t, const struct icmp* icmpp, int len, switch ( icmpp->icmp_type ) { + case ND_NEIGHBOR_ADVERT: + f = icmp_neighbor_advertisement; + break; + case ND_NEIGHBOR_SOLICIT: + f = icmp_neighbor_solicitation; + break; case ND_ROUTER_ADVERT: f = icmp_router_advertisement; break; - - case ND_REDIRECT: case ND_ROUTER_SOLICIT: + f = icmp_router_solicitation; + break; + case ND_REDIRECT: + f = icmp_redirect; + break; case ICMP6_ROUTER_RENUMBERING: default: ICMPEvent(icmp_sent, icmpp, len, 1); @@ -567,11 +563,14 @@ void ICMP_Analyzer::Context6(double t, const struct icmp* icmpp, 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_error_message; + f = icmp_packet_too_big; break; } diff --git a/src/Sessions.cc b/src/Sessions.cc index cd9d7bb250..309e841a06 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -310,8 +310,6 @@ void NetSessions::NextPacketSecondary(double /* t */, const struct pcap_pkthdr* ++num_packets_processed; - - uint32 caplen = hdr->caplen - hdr_size; if ( caplen < sizeof(struct ip) ) { @@ -446,7 +444,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, int proto = ip_hdr->NextProto(); if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP && - proto != IPPROTO_ICMP && proto != IPPROTO_ICMPV6) // Added ICMPV6, Matti + proto != IPPROTO_ICMP && proto != IPPROTO_ICMPV6) { dump_this_packet = 1; return; @@ -489,7 +487,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, caplen -= ip_hdr_len; uint32 min_hdr_len = (proto == IPPROTO_TCP) ? sizeof(struct tcphdr) : - (proto == IPPROTO_UDP ? sizeof(struct udphdr) : ICMP_MINLEN); //needs checking for ICMPV6?, Matti + (proto == IPPROTO_UDP ? sizeof(struct udphdr) : ICMP_MINLEN); if ( len < min_hdr_len ) { @@ -550,12 +548,11 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, break; } - case IPPROTO_ICMPV6: // new case, identical to ICMP, is this correct?? Matti + case IPPROTO_ICMPV6: { const struct icmp* icmpp = (const struct icmp *) data; id.src_port = icmpp->icmp_type; - //printf("TYPE: %d\n", id.src_port); //testing, Matti id.dst_port = ICMP6_counterpart(icmpp->icmp_type, icmpp->icmp_code, id.is_one_way); @@ -565,8 +562,8 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, d = &icmp_conns; break; - } + default: Weird(fmt("unknown_protocol %d", proto), hdr, pkt); return; @@ -735,13 +732,11 @@ Val* NetSessions::BuildHeader(const struct ip* ip) break; } - case IPPROTO_ICMPV6: //Added, Matti + case IPPROTO_ICMPV6: { const struct icmp* icmpp = (const struct icmp *) data; RecordVal* icmp_hdr = new RecordVal(icmp_hdr_type); - //printf("datalen:%d",data_len); //Testing, Matti - icmp_hdr->Assign(0, new Val(icmpp->icmp_type, TYPE_COUNT)); pkt_hdr->Assign(3, icmp_hdr); @@ -1065,7 +1060,7 @@ Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id, case IPPROTO_UDP: tproto = TRANSPORT_UDP; break; - case IPPROTO_ICMPV6: //TransportProto Hack + case IPPROTO_ICMPV6: tproto = TRANSPORT_ICMP; break; default: @@ -1150,6 +1145,7 @@ bool NetSessions::IsLikelyServerPort(uint32 port, TransportProto proto) const port |= UDP_PORT_MASK; else if ( proto == TRANSPORT_ICMP ) port |= ICMP_PORT_MASK; + return port_cache.find(port) != port_cache.end(); } diff --git a/src/Val.cc b/src/Val.cc index e19fffa379..db6e9eb23a 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -788,6 +788,7 @@ PortVal::PortVal(uint32 p, TransportProto port_type) : Val(TYPE_PORT) case TRANSPORT_ICMP: p |= ICMP_PORT_MASK; break; + default: break; // "other" } diff --git a/src/Val.h b/src/Val.h index fe6164e48f..ae8c53308e 100644 --- a/src/Val.h +++ b/src/Val.h @@ -534,7 +534,6 @@ public: int IsUDP() const; int IsICMP() const; - TransportProto PortType() const { if ( IsTCP() ) diff --git a/src/event.bif b/src/event.bif index db7464db55..d4148a2611 100644 --- a/src/event.bif +++ b/src/event.bif @@ -798,6 +798,24 @@ event icmp_echo_request%(c: connection, icmp: icmp_conn, id: count, seq: count, ## icmp_time_exceeded icmp_unreachable event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%); +## Generated for all ICMP error messages that are not handled separately with dedicated +## ICMP events. Bro's ICMP analyzer handles a number of ICMP messages directly +## with dedicated events. This handler acts as a fallback for those it doesn't. +## The *icmp* record provides more information about the message. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard +## connection record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect +## icmp_time_exceeded icmp_unreachable +event icmp_error_message%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); + ## Generated for ICMP *destination unreachable* messages. ## ## See `Wikipedia @@ -821,13 +839,28 @@ event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, pa ## icmp_time_exceeded 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_router_advertisement%(c: connection, icmp: icmp_conn%); - - - -event icmp6_placeholder%(c: connection, icmp: icmp_conn, ICMP6: bool%); - +## Generated for ICMP *packet too big* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## code: The ICMP code of the *too big* message. +## +## context: A record with specifics of the original packet that the message refers +## to. *Too big* messages should include the original IP header from the packet +## that triggered them, and Bro parses that into the *context* structure. Note +## that if the *too big* includes only a partial IP header for some reason, no +## fields of *context* will be filled out. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect icmp_sent +## icmp_time_exceeded +event icmp_packet_too_big%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); ## Generated for ICMP *time exceeded* messages. ## @@ -852,6 +885,89 @@ event icmp6_placeholder%(c: connection, icmp: icmp_conn, ICMP6: bool%); ## icmp_unreachable event icmp_time_exceeded%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); +## Generated for ICMP *parameter problem* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## code: The ICMP code of the *parameter problem* message. +## +## context: A record with specifics of the original packet that the message refers +## to. *Parameter problem* messages should include the original IP header from the packet +## that triggered them, and Bro parses that into the *context* structure. Note that +## if the *parameter problem* includes only a partial IP header for some reason, no fields +## of *context* will be filled out. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect icmp_sent +## icmp_unreachable +event icmp_parameter_problem%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); + +## Generated for ICMP *router solicitation* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_router_solicitation%(c: connection, icmp: icmp_conn%); + +## Generated for ICMP *router advertisement* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_router_advertisement%(c: connection, icmp: icmp_conn%); + +## Generated for ICMP *neighbor solicitation* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_neighbor_solicitation%(c: connection, icmp: icmp_conn%); + +## Generated for ICMP *neighbor advertisement* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_neighbor_advertisement%(c: connection, icmp: icmp_conn%); + ## Generated for ICMP *redirect* messages. ## ## See `Wikipedia diff --git a/src/net_util.cc b/src/net_util.cc index d66e56711f..a367429257 100644 --- a/src/net_util.cc +++ b/src/net_util.cc @@ -90,7 +90,7 @@ int udp_checksum(const struct ip* ip, const struct udphdr* up, int len) int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len) { // UDP over IPv6 uses the same checksum function as over IPv4 but a - // different pseuod-header over which it is computed. + // different pseudo-header over which it is computed. uint32 sum; if ( len % 2 == 1 ) @@ -116,8 +116,8 @@ int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len) int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len) { - // ICMP6 uses the same checksum function as over ICMP4 but a different - // pseuod-header over which it is computed. + // ICMP6 uses the same checksum function as ICMP4 but a different + // pseudo-header over which it is computed. uint32 sum; if ( len % 2 == 1 )