protodetect: use both directions over UDP

As is already done for TCP

Ticket: #2757
pull/7423/head
Philippe Antoine 6 years ago committed by Victor Julien
parent edd163252d
commit 3051f7f23f

@ -685,8 +685,9 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
/* if we don't know the proto yet and we have received a stream /* if we don't know the proto yet and we have received a stream
* initializer message, we run proto detection. * initializer message, we run proto detection.
* We receive 2 stream init msgs (one for each direction) but we * We receive 2 stream init msgs (one for each direction), we
* only run the proto detection once. */ * only run the proto detection for both and emit an event
* in the case protocols mismatch. */
if (alproto == ALPROTO_UNKNOWN && (flags & STREAM_START)) { if (alproto == ALPROTO_UNKNOWN && (flags & STREAM_START)) {
DEBUG_VALIDATE_BUG_ON(FlowChangeProto(f)); DEBUG_VALIDATE_BUG_ON(FlowChangeProto(f));
/* run protocol detection */ /* run protocol detection */
@ -785,8 +786,10 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
int AppLayerHandleUdp(ThreadVars *tv, AppLayerThreadCtx *tctx, Packet *p, Flow *f) int AppLayerHandleUdp(ThreadVars *tv, AppLayerThreadCtx *tctx, Packet *p, Flow *f)
{ {
SCEnter(); SCEnter();
AppProto *alproto;
AppProto *alproto_otherdir;
if (f->alproto == ALPROTO_FAILED) { if (f->alproto_ts == ALPROTO_FAILED && f->alproto_tc == ALPROTO_FAILED) {
SCReturnInt(0); SCReturnInt(0);
} }
@ -794,33 +797,75 @@ int AppLayerHandleUdp(ThreadVars *tv, AppLayerThreadCtx *tctx, Packet *p, Flow *
uint8_t flags = 0; uint8_t flags = 0;
if (p->flowflags & FLOW_PKT_TOSERVER) { if (p->flowflags & FLOW_PKT_TOSERVER) {
flags |= STREAM_TOSERVER; flags |= STREAM_TOSERVER;
alproto = &f->alproto_ts;
alproto_otherdir = &f->alproto_tc;
} else { } else {
flags |= STREAM_TOCLIENT; flags |= STREAM_TOCLIENT;
alproto = &f->alproto_tc;
alproto_otherdir = &f->alproto_ts;
} }
AppLayerProfilingReset(tctx); AppLayerProfilingReset(tctx);
/* if the protocol is still unknown, run detection */ /* if the protocol is still unknown, run detection */
if (f->alproto == ALPROTO_UNKNOWN) { if (*alproto == ALPROTO_UNKNOWN) {
SCLogDebug("Detecting AL proto on udp mesg (len %" PRIu32 ")", SCLogDebug("Detecting AL proto on udp mesg (len %" PRIu32 ")",
p->payload_len); p->payload_len);
bool reverse_flow = false; bool reverse_flow = false;
PACKET_PROFILING_APP_PD_START(tctx); PACKET_PROFILING_APP_PD_START(tctx);
f->alproto = AppLayerProtoDetectGetProto(tctx->alpd_tctx, *alproto = AppLayerProtoDetectGetProto(
f, p->payload, p->payload_len, tctx->alpd_tctx, f, p->payload, p->payload_len, IPPROTO_UDP, flags, &reverse_flow);
IPPROTO_UDP, flags, &reverse_flow);
PACKET_PROFILING_APP_PD_END(tctx); PACKET_PROFILING_APP_PD_END(tctx);
if (f->alproto != ALPROTO_UNKNOWN) { switch (*alproto) {
AppLayerIncFlowCounter(tv, f); case ALPROTO_UNKNOWN:
if (*alproto_otherdir != ALPROTO_UNKNOWN) {
if (p->flowflags & FLOW_PKT_TOSERVER) { // Use recognized side
f->alproto_ts = f->alproto; f->alproto = *alproto_otherdir;
} else { // do not keep ALPROTO_UNKNOWN for this side so as not to loop
f->alproto_tc = f->alproto; *alproto = *alproto_otherdir;
if (*alproto_otherdir == ALPROTO_FAILED) {
SCLogDebug("ALPROTO_UNKNOWN flow %p", f);
}
} else {
// First side of protocol is unknown
*alproto = ALPROTO_FAILED;
}
break;
case ALPROTO_FAILED:
if (*alproto_otherdir != ALPROTO_UNKNOWN) {
// Use recognized side
f->alproto = *alproto_otherdir;
if (*alproto_otherdir == ALPROTO_FAILED) {
SCLogDebug("ALPROTO_UNKNOWN flow %p", f);
}
}
// else wait for second side of protocol
break;
default:
if (*alproto_otherdir != ALPROTO_UNKNOWN && *alproto_otherdir != ALPROTO_FAILED) {
if (*alproto_otherdir != *alproto) {
AppLayerDecoderEventsSetEventRaw(
&p->app_layer_events, APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS);
// data already sent to parser, we cannot change the protocol to use the one
// of the server
}
} else {
f->alproto = *alproto;
}
}
if (*alproto_otherdir == ALPROTO_UNKNOWN) {
if (f->alproto == ALPROTO_UNKNOWN) {
// so as to increase stat about .app_layer.flow.failed_udp
f->alproto = ALPROTO_FAILED;
} }
// If the other side is unknown, this is the first packet of the flow
AppLayerIncFlowCounter(tv, f);
}
// parse the data if we recognized one protocol
if (f->alproto != ALPROTO_UNKNOWN && f->alproto != ALPROTO_FAILED) {
if (reverse_flow) { if (reverse_flow) {
SCLogDebug("reversing flow after proto detect told us so"); SCLogDebug("reversing flow after proto detect told us so");
PacketSwap(p); PacketSwap(p);
@ -832,10 +877,6 @@ int AppLayerHandleUdp(ThreadVars *tv, AppLayerThreadCtx *tctx, Packet *p, Flow *
r = AppLayerParserParse(tv, tctx->alp_tctx, f, f->alproto, r = AppLayerParserParse(tv, tctx->alp_tctx, f, f->alproto,
flags, p->payload, p->payload_len); flags, p->payload, p->payload_len);
PACKET_PROFILING_APP_END(tctx, f->alproto); PACKET_PROFILING_APP_END(tctx, f->alproto);
} else {
f->alproto = ALPROTO_FAILED;
AppLayerIncFlowCounter(tv, f);
SCLogDebug("ALPROTO_UNKNOWN flow %p", f);
} }
PACKET_PROFILING_APP_STORE(tctx, p); PACKET_PROFILING_APP_STORE(tctx, p);
/* we do only inspection in one direction, so flag both /* we do only inspection in one direction, so flag both

Loading…
Cancel
Save