From: Josh Date: Thu, 2 Oct 2014 15:49:44 +0000 (-0500) Subject: Fixing main Detect() loop ... now gets correct ip_proto() X-Git-Tag: 3.0.0-233~1397^2~24^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ebd96f8ea3d70131138f435ec17d442909cdbad3;p=thirdparty%2Fsnort3.git Fixing main Detect() loop ... now gets correct ip_proto() --- diff --git a/src/detection/detect.cc b/src/detection/detect.cc index 25bc60b9c..8d3e2dafa 100644 --- a/src/detection/detect.cc +++ b/src/detection/detect.cc @@ -301,14 +301,14 @@ int CheckTagging(Packet *p) * 0 == no detection * ***************************************************************************/ -int Detect(Packet * p) +bool Detect(Packet * p) { int detected = 0; PROFILE_VARS; if ((p == NULL) || !p->ptrs.ip_api.is_valid()) { - return 0; + return false; } if (p->packet_flags & PKT_PASS_RULE) @@ -316,55 +316,49 @@ int Detect(Packet * p) /* If we've already seen a pass rule on this, * no need to continue do inspection. */ - return 0; + return false; } // FIXIT-M: Curently, if a rule is found on any IP layer, we // perform the detect routine on the entire packet. // Instead, we should only perform detect on that // layer!! - bool proto_found = false; - ip::IpApi tmp_api; - int8_t curr_layer = p->num_layers - 1; - while (layer::set_inner_ip_api(p, tmp_api, curr_layer)) + int curr_layer = p->num_layers - 1; + uint8_t ip_proto; // set in function + + while (p->ip_proto_next(curr_layer, ip_proto)) { - // FIXIT-H J We may be checking for an IP6 extension! - if (snort_conf->ip_proto_array[tmp_api.proto()]) + if (snort_conf->ip_proto_array[ip_proto]) { - proto_found = true; - break; - } - } - - if (!proto_found) - return 0; +# ifdef PPM_MGR + /* + * Packet Performance Monitoring + * (see if preprocessing took too long) + */ + if( PPM_PKTS_ENABLED() ) + { + PPM_GET_TIME(); + PPM_PACKET_TEST(); + if( PPM_PACKET_ABORT_FLAG() ) + return false; + } +# endif /* PPM_MGR */ -#ifdef PPM_MGR - /* - * Packet Performance Monitoring - * (see if preprocessing took too long) - */ - if( PPM_PKTS_ENABLED() ) - { - PPM_GET_TIME(); - PPM_PACKET_TEST(); + /* + ** This is where we short circuit so + ** that we can do IP checks. + */ + MODULE_PROFILE_START(detectPerfStats); + detected = fpEvalPacket(p); + MODULE_PROFILE_END(detectPerfStats); - if( PPM_PACKET_ABORT_FLAG() ) - return 0; + return detected; + } } -#endif - - /* - ** This is where we short circuit so - ** that we can do IP checks. - */ - MODULE_PROFILE_START(detectPerfStats); - detected = fpEvalPacket(p); - MODULE_PROFILE_END(detectPerfStats); - return detected; + return false; } int CheckAddrPort( diff --git a/src/detection/detect.h b/src/detection/detect.h index 5b0b42227..4a7d5de69 100644 --- a/src/detection/detect.h +++ b/src/detection/detect.h @@ -50,7 +50,7 @@ extern THREAD_LOCAL ProfileStats detectPerfStats; /* detection/manipulation funcs */ void snort_ignore(Packet*); void snort_inspect(Packet*); -SO_PUBLIC int Detect(Packet *); +SO_PUBLIC bool Detect(Packet *); void CallOutputPlugins(Packet *); int EvalPacket(ListHead *, int, Packet * ); int EvalHeader(RuleTreeNode *, Packet *, int); diff --git a/src/protocols/packet.cc b/src/protocols/packet.cc index 339e9b2e8..903ddc3e0 100644 --- a/src/protocols/packet.cc +++ b/src/protocols/packet.cc @@ -72,3 +72,47 @@ uint8_t Packet::ip_proto_next() const return IPPROTO_ID_RESERVED; } + +static inline bool is_ip_protocol(const uint16_t proto) +{ + switch(proto) + { + case IPPROTO_ID_HOPOPTS: + case IPPROTO_ID_DSTOPTS: + case IPPROTO_ID_ROUTING: + case IPPROTO_ID_FRAGMENT: + case IPPROTO_ID_AUTH: + case IPPROTO_ID_ESP: + case IPPROTO_ID_MOBILITY: + case IPPROTO_ID_IPIP: + case IPPROTO_ID_IPV6: + case ETHERTYPE_IPV4: + case ETHERTYPE_IPV6: + return true; + default: + return false; + } +} + +bool Packet::ip_proto_next(int &lyr, uint8_t& proto) const +{ + if (lyr < 0) + return false; + + // lyr[0] will always return false + // walk past any ip6 options/IP protocols + while (is_ip_protocol(layers[lyr].prot_id)) + --lyr; + + while (lyr >= 0) + { + if (is_ip_protocol(layers[lyr].prot_id)) + return true; + else + proto = layers[lyr].prot_id; + + --lyr; + } + + return false; +} diff --git a/src/protocols/packet.h b/src/protocols/packet.h index 0090ab335..244f3073a 100644 --- a/src/protocols/packet.h +++ b/src/protocols/packet.h @@ -224,11 +224,29 @@ struct SO_PUBLIC Packet * can frequently be an IP extension. Therefore, this function * return the protocol ID of the first protocol after all the * IP layers. For instance, if the stack is - * eth::ip6::hop_opts::ipv6_routing::UDP - * this function return 17 == IPPROTO_UDP == IPPROTO_ID_UDP + * eth::ip4::udp::teredo::ip6::hop_opts::ipv6_routing::tcp + * this function return 6 == IPPROTO_TCP == IPPROTO_ID_TCP */ uint8_t ip_proto_next() const; + /* Similar to above. However, this function + * can be called in a loop to get all of the ip_proto's. + * NOTE: Will only return protocols of validly decoded layers. + * + * PARAMS: + * lyr - zero based layer from which to start searching outward. + * will always point to an IP protocol or IP extension. + * ip_proto - the ip_proto (read above) for the next, outermost IP layer + * EXAMPLE: + * + * int lyr = p->num_layers - 1; + * while ( ip_proto_next(lyr, ip_proto)) + * { + * .... + * } + */ + bool ip_proto_next(int &lyr, uint8_t& proto) const; + inline void reset() { memset(&flow, '\0', offsetof(Packet, pkth));