applayer: add registration interface for parsers

Add a common structure definition to contain all required elements
required for registering a parser.
This also reduces the risk of incorrectly registering a parser: the
compiler will type-check functions.

The registration function allows factorization of the code. It can be
used to register parsers, but is not mandatory.

If extra registration code (for functions not in the structure)
it is still possible by calling the C functions after the registration.
pull/3009/head
Pierre Chifflier 7 years ago committed by Victor Julien
parent 862abd2fe4
commit 3edc76533c

@ -42,6 +42,7 @@ app-layer-smtp.c app-layer-smtp.h \
app-layer-nfs-tcp.c app-layer-nfs-tcp.h \
app-layer-nfs-udp.c app-layer-nfs-udp.h \
app-layer-ntp.c app-layer-ntp.h \
app-layer-register.c app-layer-register.h \
app-layer-template.c app-layer-template.h \
app-layer-ssh.c app-layer-ssh.h \
app-layer-ssl.c app-layer-ssl.h \

@ -0,0 +1,185 @@
/* Copyright (C) 2017 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file
*
* \author Pierre Chifflier <chifflier@wzdftpd.net>
*
* Parser registration functions.
*/
#include "suricata-common.h"
#include "stream.h"
#include "conf.h"
#include "app-layer-detect-proto.h"
#include "app-layer-parser.h"
#include "app-layer-register.h"
static const char * IpProtoToString(int ip_proto);
AppProto AppLayerRegisterProtocolDetection(const struct AppLayerParser *p, int enable_default)
{
AppProto alproto;
const char *ip_proto_str = NULL;
if (p == NULL)
FatalError(SC_ERR_FATAL, "Call to %s with NULL pointer.", __FUNCTION__);
alproto = StringToAppProto(p->name);
if (alproto == ALPROTO_UNKNOWN || alproto == ALPROTO_FAILED)
FatalError(SC_ERR_FATAL, "Unknown or invalid AppProto '%s'.", p->name);
ip_proto_str = IpProtoToString(p->ip_proto);
if (ip_proto_str == NULL)
FatalError(SC_ERR_FATAL, "Unknown or unsupported ip_proto field in parser '%s'", p->name);
SCLogDebug("%s %s protocol detection enabled.", ip_proto_str, p->name);
AppLayerProtoDetectRegisterProtocol(alproto, p->name);
if (RunmodeIsUnittests()) {
SCLogDebug("Unittest mode, registering default configuration.");
AppLayerProtoDetectPPRegister(p->ip_proto, p->default_port,
alproto, p->min_depth, p->max_depth, STREAM_TOSERVER,
p->ProbeTS, p->ProbeTC);
}
else {
if (!AppLayerProtoDetectPPParseConfPorts(ip_proto_str, p->ip_proto,
p->name, alproto, p->min_depth, p->max_depth,
p->ProbeTS, p->ProbeTC)) {
if (enable_default != 0) {
SCLogDebug("No %s app-layer configuration, enabling %s"
" detection %s detection on port %s.",
p->name, p->name, ip_proto_str, p->default_port);
AppLayerProtoDetectPPRegister(p->ip_proto,
p->default_port, alproto,
p->min_depth, p->max_depth, STREAM_TOSERVER,
p->ProbeTS, p->ProbeTC);
} else {
SCLogDebug("No %s app-layer configuration for detection port (%s).",
p->name, ip_proto_str);
}
}
}
return alproto;
}
int AppLayerRegisterParser(const struct AppLayerParser *p, AppProto alproto)
{
const char *ip_proto_str = NULL;
if (p == NULL)
FatalError(SC_ERR_FATAL, "Call to %s with NULL pointer.", __FUNCTION__);
if (alproto == ALPROTO_UNKNOWN || alproto >= ALPROTO_FAILED)
FatalError(SC_ERR_FATAL, "Unknown or invalid AppProto '%s'.", p->name);
ip_proto_str = IpProtoToString(p->ip_proto);
if (ip_proto_str == NULL)
FatalError(SC_ERR_FATAL, "Unknown or unsupported ip_proto field in parser '%s'", p->name);
SCLogDebug("Registering %s protocol parser.", p->name);
/* Register functions for state allocation and freeing. A
* state is allocated for every new flow. */
AppLayerParserRegisterStateFuncs(p->ip_proto, alproto,
p->StateAlloc, p->StateFree);
/* Register request parser for parsing frame from server to server. */
AppLayerParserRegisterParser(p->ip_proto, alproto,
STREAM_TOSERVER, p->ParseTS);
/* Register response parser for parsing frames from server to client. */
AppLayerParserRegisterParser(p->ip_proto, alproto,
STREAM_TOCLIENT, p->ParseTC);
/* Register a function to be called by the application layer
* when a transaction is to be freed. */
AppLayerParserRegisterTxFreeFunc(p->ip_proto, alproto,
p->StateTransactionFree);
/* Register a function to return the current transaction count. */
AppLayerParserRegisterGetTxCnt(p->ip_proto, alproto,
p->StateGetTxCnt);
/* Transaction handling. */
AppLayerParserRegisterGetStateProgressCompletionStatus(alproto,
p->StateGetProgressCompletionStatus);
AppLayerParserRegisterGetStateProgressFunc(p->ip_proto, alproto,
p->StateGetProgress);
AppLayerParserRegisterGetTx(p->ip_proto, alproto,
p->StateGetTx);
if (p->StateGetTxLogged && p->StateSetTxLogged) {
AppLayerParserRegisterLoggerFuncs(p->ip_proto, alproto,
p->StateGetTxLogged, p->StateSetTxLogged);
}
/* Application layer event handling. */
if (p->StateHasEvents) {
AppLayerParserRegisterHasEventsFunc(p->ip_proto, alproto,
p->StateHasEvents);
}
/* What is this being registered for? */
AppLayerParserRegisterDetectStateFuncs(p->ip_proto, alproto,
p->StateHasTxDetectState, p->GetTxDetectState, p->SetTxDetectState);
if (p->StateGetEventInfo) {
AppLayerParserRegisterGetEventInfo(p->ip_proto, alproto,
p->StateGetEventInfo);
}
if (p->StateGetEvents) {
AppLayerParserRegisterGetEventsFunc(p->ip_proto, alproto,
p->StateGetEvents);
}
if (p->LocalStorageAlloc && p->LocalStorageFree) {
AppLayerParserRegisterLocalStorageFunc(p->ip_proto, alproto,
p->LocalStorageAlloc, p->LocalStorageFree);
}
if (p->GetTxMpmIDs && p->SetTxMpmIDs) {
AppLayerParserRegisterMpmIDsFuncs(p->ip_proto, alproto,
p->GetTxMpmIDs, p->SetTxMpmIDs);
}
if (p->StateGetFiles) {
AppLayerParserRegisterGetFilesFunc(p->ip_proto, alproto,
p->StateGetFiles);
}
return 0;
}
static const char * IpProtoToString(int ip_proto)
{
switch (ip_proto) {
case IPPROTO_TCP:
return "tcp";
case IPPROTO_UDP:
return "udp";
default:
return NULL;
};
}

@ -0,0 +1,90 @@
/* Copyright (C) 2017 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file
*
* \author Pierre Chifflier <chifflier@wzdftpd.net>
*/
#ifndef __APP_LAYER_REGISTER_H__
#define __APP_LAYER_REGISTER_H__
typedef struct AppLayerParser {
const char *name;
const char *default_port;
int ip_proto;
ProbingParserFPtr ProbeTS;
ProbingParserFPtr ProbeTC;
uint16_t min_depth;
uint16_t max_depth;
void *(*StateAlloc)(void);
void (*StateFree)(void *);
AppLayerParserFPtr ParseTS;
AppLayerParserFPtr ParseTC;
uint64_t (*StateGetTxCnt)(void *alstate);
void *(*StateGetTx)(void *alstate, uint64_t tx_id);
void (*StateTransactionFree)(void *, uint64_t);
int (*StateGetProgressCompletionStatus)(uint8_t direction);
int (*StateGetProgress)(void *alstate, uint8_t direction);
int (*StateGetTxLogged)(void *alstate, void *tx, uint32_t logger);
void (*StateSetTxLogged)(void *alstate, void *tx, uint32_t logger);
DetectEngineState *(*GetTxDetectState)(void *tx);
int (*SetTxDetectState)(void *alstate, void *tx, DetectEngineState *);
int (*StateHasTxDetectState)(void *alstate);
int (*StateHasEvents)(void *);
AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t);
int (*StateGetEventInfo)(const char *event_name,
int *event_id, AppLayerEventType *event_type);
void *(*LocalStorageAlloc)(void);
void (*LocalStorageFree)(void *);
uint64_t (*GetTxMpmIDs)(void *tx);
int (*SetTxMpmIDs)(void *tx, uint64_t);
FileContainer *(*StateGetFiles)(void *, uint8_t);
} AppLayerParser;
/**
* \brief App layer protocol detection function.
*
* \param parser The parser declaration structure.
* \param enable_default A boolean to indicate if default port configuration should be used if none given
*
* \retval The AppProto constant if successful. On error, this function never returns.
*/
AppProto AppLayerRegisterProtocolDetection(const struct AppLayerParser *parser, int enable_default);
/**
* \brief App layer protocol registration function.
*
* \param parser The parser declaration structure.
* \param alproto The application layer protocol identifier.
*
* \retval 0 if successful. On error, this function never returns.
*/
int AppLayerRegisterParser(const struct AppLayerParser *p, AppProto alproto);
#endif /* __APP_LAYER_REGISTER_H__ */
Loading…
Cancel
Save