[features]
lua = []
+experimental = ["ntp-parser"]
[dependencies]
nom = "~3.0"
libc = "~0.2.0"
crc = "~1.4.0"
+
+ntp-parser = { version = "^0", optional = true }
"libc::c_void": "void",
+ "libc::c_char": "char",
"libc::c_int": "int",
"c_int": "int",
"libc::int8_t": "int8_t",
"DNSTransaction": "RSDNSTransaction",
"NFSState": "NFSState",
"NFSTransaction": "NFSTransaction",
+ "NTPState": "NTPState",
+ "NTPTransaction": "NTPTransaction",
"JsonT": "json_t",
"DetectEngineState": "DetectEngineState",
"core::DetectEngineState": "DetectEngineState",
"core::AppLayerDecoderEvents": "AppLayerDecoderEvents",
+ "core::AppLayerEventType": "AppLayerEventType",
"CLuaState": "lua_State",
"Store": "Store",
}
pub enum DetectEngineState {}
pub enum AppLayerDecoderEvents {}
+// From app-layer-events.h
+pub type AppLayerEventType = libc::c_int;
+pub const APP_LAYER_EVENT_TYPE_TRANSACTION : i32 = 1;
+pub const APP_LAYER_EVENT_TYPE_PACKET : i32 = 2;
+
// From stream.h.
pub const STREAM_TOSERVER: u8 = 0x04;
pub const STREAM_TOCLIENT: u8 = 0x08;
pub mod dns;
pub mod nfs;
+
+#[cfg(feature = "experimental")]
+pub mod ntp;
--- /dev/null
+/* 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.
+ */
+
+// written by Pierre Chifflier <chifflier@wzdftpd.net>
+
+pub mod ntp;
--- /dev/null
+/* 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.
+ */
+
+// written by Pierre Chifflier <chifflier@wzdftpd.net>
+
+extern crate ntp_parser;
+use self::ntp_parser::*;
+use core;
+use applayer;
+use libc;
+use std;
+use std::ffi::CStr;
+
+use log::*;
+
+use nom::IResult;
+
+#[repr(u32)]
+pub enum NTPEvent {
+ UnsolicitedResponse = 0,
+ MalformedData,
+ NotRequest,
+ NotResponse,
+}
+
+
+
+pub struct NTPState {
+ /// List of transactions for this session
+ transactions: Vec<NTPTransaction>,
+
+ /// Detection engine states counter
+ de_state_count: u64,
+
+ /// Events counter
+ events: u16,
+
+ /// tx counter for assigning incrementing id's to tx's
+ tx_id: u64,
+}
+
+#[derive(Debug)]
+pub struct NTPTransaction {
+ /// The NTP reference ID
+ pub xid: u32,
+
+ /// The internal transaction id
+ id: u64,
+
+ /// The detection engine state, if present
+ de_state: Option<*mut core::DetectEngineState>,
+
+ /// The events associated with this transaction
+ events: *mut core::AppLayerDecoderEvents,
+
+ logged: applayer::LoggerFlags,
+}
+
+
+
+impl NTPState {
+ pub fn new() -> NTPState {
+ NTPState{
+ transactions: Vec::new(),
+ de_state_count: 0,
+ events: 0,
+ tx_id: 0,
+ }
+ }
+}
+
+impl NTPState {
+ fn parse(&mut self, i: &[u8], _direction: u8) -> i8 {
+ match parse_ntp(i) {
+ IResult::Done(_,ref msg) => {
+ // SCLogDebug!("parse_ntp: {:?}",msg);
+ if msg.mode == 1 || msg.mode == 3 {
+ let mut tx = self.new_tx();
+ // use the reference id as identifier
+ tx.xid = msg.ref_id;
+ self.transactions.push(tx);
+ }
+ 0
+ },
+ IResult::Incomplete(_) => {
+ SCLogDebug!("Insufficient data while parsing NTP data");
+ self.set_event(NTPEvent::MalformedData);
+ -1
+ },
+ IResult::Error(_) => {
+ SCLogDebug!("Error while parsing NTP data");
+ self.set_event(NTPEvent::MalformedData);
+ -1
+ },
+ }
+ }
+
+ fn free(&mut self) {
+ // All transactions are freed when the `transactions` object is freed.
+ // But let's be explicit
+ self.transactions.clear();
+ }
+
+ fn new_tx(&mut self) -> NTPTransaction {
+ self.tx_id += 1;
+ NTPTransaction::new(self.tx_id)
+ }
+
+ pub fn get_tx_by_id(&mut self, tx_id: u64) -> Option<&NTPTransaction> {
+ self.transactions.iter().find(|&tx| tx.id == tx_id + 1)
+ }
+
+ fn free_tx(&mut self, tx_id: u64) {
+ let tx = self.transactions.iter().position(|ref tx| tx.id == tx_id + 1);
+ debug_assert!(tx != None);
+ if let Some(idx) = tx {
+ let _ = self.transactions.remove(idx);
+ }
+ }
+
+ /// Set an event. The event is set on the most recent transaction.
+ pub fn set_event(&mut self, event: NTPEvent) {
+ if let Some(tx) = self.transactions.last_mut() {
+ let ev = event as u8;
+ core::sc_app_layer_decoder_events_set_event_raw(&mut tx.events, ev);
+ self.events += 1;
+ }
+ }
+}
+
+impl NTPTransaction {
+ pub fn new(id: u64) -> NTPTransaction {
+ NTPTransaction {
+ xid: 0,
+ id: id,
+ de_state: None,
+ events: std::ptr::null_mut(),
+ logged: applayer::LoggerFlags::new(),
+ }
+ }
+
+ fn free(&mut self) {
+ if self.events != std::ptr::null_mut() {
+ core::sc_app_layer_decoder_events_free_events(&mut self.events);
+ }
+ }
+}
+
+impl Drop for NTPTransaction {
+ fn drop(&mut self) {
+ self.free();
+ }
+}
+
+
+/// TOSERVER probe function
+#[no_mangle]
+pub extern "C" fn rs_ntp_probe(input: *const libc::uint8_t, len: libc::uint32_t)
+ -> libc::int8_t
+{
+ let slice: &[u8] = unsafe {
+ std::slice::from_raw_parts(input as *mut u8, len as usize)
+ };
+ match parse_ntp(slice) {
+ IResult::Done(_, ref msg) => {
+ if msg.version == 3 || msg.version == 4 {
+ return 1;
+ } else {
+ return -1;
+ }
+ },
+ IResult::Incomplete(_) => {
+ return 0;
+ },
+ IResult::Error(_) => {
+ return -1;
+ },
+ }
+}
+
+
+
+
+
+
+
+/// Returns *mut NTPState
+#[no_mangle]
+pub extern "C" fn rs_ntp_state_new() -> *mut libc::c_void {
+ let state = NTPState::new();
+ let boxed = Box::new(state);
+ return unsafe{std::mem::transmute(boxed)};
+}
+
+/// Params:
+/// - state: *mut NTPState as void pointer
+#[no_mangle]
+pub extern "C" fn rs_ntp_state_free(state: *mut libc::c_void) {
+ // Just unbox...
+ let mut ntp_state: Box<NTPState> = unsafe{std::mem::transmute(state)};
+ ntp_state.free();
+}
+
+#[no_mangle]
+pub extern "C" fn rs_ntp_parse_request(_flow: *const core::Flow,
+ state: &mut NTPState,
+ _pstate: *const libc::c_void,
+ input: *const libc::uint8_t,
+ input_len: u32,
+ _data: *const libc::c_void) -> i8 {
+ let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)};
+ state.parse(buf, 0)
+}
+
+#[no_mangle]
+pub extern "C" fn rs_ntp_parse_response(_flow: *const core::Flow,
+ state: &mut NTPState,
+ _pstate: *const libc::c_void,
+ input: *const libc::uint8_t,
+ input_len: u32,
+ _data: *const libc::c_void) -> i8 {
+ let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)};
+ state.parse(buf, 1)
+}
+
+#[no_mangle]
+pub extern "C" fn rs_ntp_state_get_tx(state: &mut NTPState,
+ tx_id: libc::uint64_t)
+ -> *mut NTPTransaction
+{
+ match state.get_tx_by_id(tx_id) {
+ Some(tx) => unsafe{std::mem::transmute(tx)},
+ None => std::ptr::null_mut(),
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn rs_ntp_state_get_tx_count(state: &mut NTPState)
+ -> libc::uint64_t
+{
+ state.tx_id
+}
+
+#[no_mangle]
+pub extern "C" fn rs_ntp_state_tx_free(state: &mut NTPState,
+ tx_id: libc::uint64_t)
+{
+ state.free_tx(tx_id);
+}
+
+#[no_mangle]
+pub extern "C" fn rs_ntp_state_progress_completion_status(
+ _direction: libc::uint8_t)
+ -> libc::c_int
+{
+ return 1;
+}
+
+#[no_mangle]
+pub extern "C" fn rs_ntp_tx_get_alstate_progress(_tx: &mut NTPTransaction,
+ _direction: libc::uint8_t)
+ -> libc::uint8_t
+{
+ 1
+}
+
+
+
+
+
+#[no_mangle]
+pub extern "C" fn rs_ntp_tx_set_logged(_state: &mut NTPState,
+ tx: &mut NTPTransaction,
+ logger: libc::uint32_t)
+{
+ tx.logged.set_logged(logger);
+}
+
+#[no_mangle]
+pub extern "C" fn rs_ntp_tx_get_logged(_state: &mut NTPState,
+ tx: &mut NTPTransaction,
+ logger: libc::uint32_t)
+ -> i8
+{
+ if tx.logged.is_logged(logger) {
+ return 1;
+ }
+ return 0;
+}
+
+
+#[no_mangle]
+pub extern "C" fn rs_ntp_state_set_tx_detect_state(
+ state: &mut NTPState,
+ tx: &mut NTPTransaction,
+ de_state: &mut core::DetectEngineState)
+{
+ state.de_state_count += 1;
+ tx.de_state = Some(de_state);
+}
+
+#[no_mangle]
+pub extern "C" fn rs_ntp_state_get_tx_detect_state(
+ tx: &mut NTPTransaction)
+ -> *mut core::DetectEngineState
+{
+ match tx.de_state {
+ Some(ds) => ds,
+ None => std::ptr::null_mut(),
+ }
+}
+
+
+#[no_mangle]
+pub extern "C" fn rs_ntp_state_has_events(state: &mut NTPState) -> u8 {
+ if state.events > 0 {
+ return 1;
+ }
+ return 0;
+}
+
+#[no_mangle]
+pub extern "C" fn rs_ntp_state_get_events(state: &mut NTPState,
+ tx_id: libc::uint64_t)
+ -> *mut core::AppLayerDecoderEvents
+{
+ match state.get_tx_by_id(tx_id) {
+ Some(tx) => tx.events,
+ _ => std::ptr::null_mut(),
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn rs_ntp_state_get_event_info(event_name: *const libc::c_char,
+ event_id: *mut libc::c_int,
+ event_type: *mut core::AppLayerEventType)
+ -> i8
+{
+ if event_name == std::ptr::null() { return -1; }
+ let c_event_name: &CStr = unsafe { CStr::from_ptr(event_name) };
+ let event = match c_event_name.to_str() {
+ Ok(s) => {
+ match s {
+ "malformed_data" => NTPEvent::MalformedData as i32,
+ _ => -1, // unknown event
+ }
+ },
+ Err(_) => -1, // UTF-8 conversion failed
+ };
+ unsafe{
+ *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
+ *event_id = event as libc::c_int;
+ };
+ 0
+}
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-template.c app-layer-template.h \
app-layer-ssh.c app-layer-ssh.h \
app-layer-ssl.c app-layer-ssl.h \
printf(" alproto: ALPROTO_ENIP\n");
else if (pp_pe->alproto == ALPROTO_NFS)
printf(" alproto: ALPROTO_NFS\n");
+ else if (pp_pe->alproto == ALPROTO_NTP)
+ printf(" alproto: ALPROTO_NTP\n");
else if (pp_pe->alproto == ALPROTO_TEMPLATE)
printf(" alproto: ALPROTO_TEMPLATE\n");
else if (pp_pe->alproto == ALPROTO_DNP3)
printf(" alproto: ALPROTO_ENIP\n");
else if (pp_pe->alproto == ALPROTO_NFS)
printf(" alproto: ALPROTO_NFS\n");
+ else if (pp_pe->alproto == ALPROTO_NTP)
+ printf(" alproto: ALPROTO_NTP\n");
else if (pp_pe->alproto == ALPROTO_TEMPLATE)
printf(" alproto: ALPROTO_TEMPLATE\n");
else if (pp_pe->alproto == ALPROTO_DNP3)
--- /dev/null
+/* 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 for NTP application layer running on UDP port 123.
+ */
+
+#include "suricata-common.h"
+#include "stream.h"
+#include "conf.h"
+
+#include "util-unittest.h"
+
+#include "app-layer-detect-proto.h"
+#include "app-layer-parser.h"
+
+#include "app-layer-ntp.h"
+
+#if defined(HAVE_RUST) && defined(HAVE_RUST_EXTERNAL)
+
+#include "rust-ntp-ntp-gen.h"
+
+/* The default port to probe for NTP traffic if not provided in the
+ * configuration file. */
+#define NTP_DEFAULT_PORT "123"
+
+/* The minimum size for an NTP message. */
+#define NTP_MIN_FRAME_LEN 2
+
+
+static void *NTPStateAlloc(void)
+{
+ return rs_ntp_state_new();
+}
+
+static void NTPStateFree(void *state)
+{
+ rs_ntp_state_free(state);
+}
+
+/**
+ * \brief Callback from the application layer to have a transaction freed.
+ *
+ * \param state a void pointer to the NTPState object.
+ * \param tx_id the transaction ID to free.
+ */
+static void NTPStateTxFree(void *state, uint64_t tx_id)
+{
+ rs_ntp_state_tx_free(state, tx_id);
+}
+
+static int NTPStateGetEventInfo(const char *event_name, int *event_id,
+ AppLayerEventType *event_type)
+{
+ return rs_ntp_state_get_event_info(event_name, event_id, event_type);
+}
+
+static AppLayerDecoderEvents *NTPGetEvents(void *state, uint64_t tx_id)
+{
+ return rs_ntp_state_get_events(state, tx_id);
+}
+
+static int NTPHasEvents(void *state)
+{
+ return rs_ntp_state_has_events(state);
+}
+
+/**
+ * \brief Probe the input to see if it looks like NTP.
+ *
+ * \retval ALPROTO_NTP if it looks like NTP, otherwise
+ * ALPROTO_UNKNOWN.
+ */
+static AppProto NTPProbingParser(uint8_t *input, uint32_t input_len,
+ uint32_t *offset)
+{
+ if (input_len < NTP_MIN_FRAME_LEN) {
+ return ALPROTO_UNKNOWN;
+ }
+
+ int8_t r = rs_ntp_probe(input, input_len);
+ if (r == 1) {
+ return ALPROTO_NTP;
+ } else if (r == -1) {
+ return ALPROTO_FAILED;
+ }
+
+ SCLogDebug("Protocol not detected as ALPROTO_NTP.");
+ return ALPROTO_UNKNOWN;
+}
+
+static int RustNTPParseRequest(Flow *f, void *state,
+ AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
+ void *local_data)
+{
+ SCLogDebug("RustNTPParseRequest");
+ return rs_ntp_parse_request(f, state, pstate, input, input_len,
+ local_data);
+}
+
+static int RustNTPParseResponse(Flow *f, void *state,
+ AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
+ void *local_data)
+{
+ SCLogDebug("RustNTPParseResponse");
+ return rs_ntp_parse_response(f, state, pstate, input, input_len,
+ local_data);
+}
+
+static uint64_t NTPGetTxCnt(void *state)
+{
+ return rs_ntp_state_get_tx_count(state);
+}
+
+static void *NTPGetTx(void *state, uint64_t tx_id)
+{
+ return rs_ntp_state_get_tx(state, tx_id);
+}
+
+// static void NTPSetTxLogged(void *state, void *vtx, uint32_t logger)
+// {
+// rs_ntp_tx_set_logged(state, vtx, logger);
+// }
+//
+// static int NTPGetTxLogged(void *state, void *vtx, uint32_t logger)
+// {
+// return rs_ntp_tx_get_logged(state, vtx, logger);
+// }
+
+
+
+
+
+
+
+/**
+ * \brief Called by the application layer.
+ *
+ * In most cases 1 can be returned here.
+ */
+static int NTPGetAlstateProgressCompletionStatus(uint8_t direction) {
+ return rs_ntp_state_progress_completion_status(direction);
+}
+
+/**
+ * \brief Return the state of a transaction in a given direction.
+ */
+static int NTPGetStateProgress(void *tx, uint8_t direction)
+{
+ return rs_ntp_tx_get_alstate_progress(tx, direction);
+}
+
+/**
+ * \brief Get stored Tx detect state
+ */
+static DetectEngineState *NTPGetTxDetectState(void *vtx)
+{
+ return rs_ntp_state_get_tx_detect_state(vtx);
+}
+
+/**
+ * \brief Set stored Tx detect state
+ */
+static int NTPSetTxDetectState(void *state, void *vtx,
+ DetectEngineState *s)
+{
+ rs_ntp_state_set_tx_detect_state(state, vtx, s);
+ return 0;
+}
+
+void RegisterNTPParsers(void)
+{
+ const char *proto_name = "ntp";
+
+ /* Check if NTP UDP detection is enabled. If it does not exist in
+ * the configuration file then it will be enabled by default. */
+ if (AppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name)) {
+
+ SCLogDebug("NTP UDP protocol detection enabled.");
+
+ AppLayerProtoDetectRegisterProtocol(ALPROTO_NTP, proto_name);
+
+ if (RunmodeIsUnittests()) {
+
+ SCLogDebug("Unittest mode, registeringd default configuration.");
+ AppLayerProtoDetectPPRegister(IPPROTO_UDP, NTP_DEFAULT_PORT,
+ ALPROTO_NTP, 0, NTP_MIN_FRAME_LEN, STREAM_TOSERVER,
+ NTPProbingParser, NULL);
+
+ }
+ else {
+
+ if (!AppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP,
+ proto_name, ALPROTO_NTP, 0, NTP_MIN_FRAME_LEN,
+ NTPProbingParser, NULL)) {
+ SCLogDebug("No NTP app-layer configuration, enabling NTP"
+ " detection UDP detection on port %s.",
+ NTP_DEFAULT_PORT);
+ AppLayerProtoDetectPPRegister(IPPROTO_UDP,
+ NTP_DEFAULT_PORT, ALPROTO_NTP, 0,
+ NTP_MIN_FRAME_LEN, STREAM_TOSERVER,
+ NTPProbingParser, NULL);
+ }
+
+ }
+
+ }
+
+ else {
+ SCLogDebug("Protocol detecter and parser disabled for NTP.");
+ return;
+ }
+
+ if (AppLayerParserConfParserEnabled("udp", proto_name)) {
+
+ SCLogDebug("Registering NTP protocol parser.");
+
+ /* Register functions for state allocation and freeing. A
+ * state is allocated for every new NTP flow. */
+ AppLayerParserRegisterStateFuncs(IPPROTO_UDP, ALPROTO_NTP,
+ NTPStateAlloc, NTPStateFree);
+
+ /* Register request parser for parsing frame from server to client. */
+ AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_NTP,
+ STREAM_TOSERVER, RustNTPParseRequest);
+
+ /* Register response parser for parsing frames from server to client. */
+ AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_NTP,
+ STREAM_TOCLIENT, RustNTPParseResponse);
+
+ /* Register a function to be called by the application layer
+ * when a transaction is to be freed. */
+ AppLayerParserRegisterTxFreeFunc(IPPROTO_UDP, ALPROTO_NTP,
+ NTPStateTxFree);
+
+ // AppLayerParserRegisterLoggerFuncs(IPPROTO_UDP, ALPROTO_NTP,
+ // NTPGetTxLogged, NTPSetTxLogged);
+
+ /* Register a function to return the current transaction count. */
+ AppLayerParserRegisterGetTxCnt(IPPROTO_UDP, ALPROTO_NTP,
+ NTPGetTxCnt);
+
+ /* Transaction handling. */
+ AppLayerParserRegisterGetStateProgressCompletionStatus(ALPROTO_NTP,
+ NTPGetAlstateProgressCompletionStatus);
+ AppLayerParserRegisterGetStateProgressFunc(IPPROTO_UDP,
+ ALPROTO_NTP, NTPGetStateProgress);
+ AppLayerParserRegisterGetTx(IPPROTO_UDP, ALPROTO_NTP,
+ NTPGetTx);
+
+ /* Application layer event handling. */
+ AppLayerParserRegisterHasEventsFunc(IPPROTO_UDP, ALPROTO_NTP,
+ NTPHasEvents);
+
+ /* What is this being registered for? */
+ AppLayerParserRegisterDetectStateFuncs(IPPROTO_UDP, ALPROTO_NTP,
+ NULL, NTPGetTxDetectState, NTPSetTxDetectState);
+
+ AppLayerParserRegisterGetEventInfo(IPPROTO_UDP, ALPROTO_NTP,
+ NTPStateGetEventInfo);
+ AppLayerParserRegisterGetEventsFunc(IPPROTO_UDP, ALPROTO_NTP,
+ NTPGetEvents);
+ }
+ else {
+ SCLogDebug("NTP protocol parsing disabled.");
+ }
+
+#ifdef UNITTESTS
+ AppLayerParserRegisterProtocolUnittests(IPPROTO_UDP, ALPROTO_NTP,
+ NTPParserRegisterTests);
+#endif
+}
+
+#ifdef UNITTESTS
+#endif
+
+void NTPParserRegisterTests(void)
+{
+#ifdef UNITTESTS
+#endif
+}
+
+#else /* HAVE_RUST */
+
+void RegisterNTPParsers(void)
+{
+}
+
+#endif /* HAVE_RUST */
--- /dev/null
+/* 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_NTP_H__
+#define __APP_LAYER_NTP_H__
+
+void RegisterNTPParsers(void);
+void NTPParserRegisterTests(void);
+
+/** Opaque Rust types. */
+typedef struct NTPState_ NTPState;
+typedef struct NTPTransaction_ NTPTransaction;
+
+#endif /* __APP_LAYER_NTP_H__ */
#include "app-layer-dnp3.h"
#include "app-layer-nfs-tcp.h"
#include "app-layer-nfs-udp.h"
+#include "app-layer-ntp.h"
#include "app-layer-template.h"
#include "conf.h"
RegisterDNP3Parsers();
RegisterNFSTCPParsers();
RegisterNFSUDPParsers();
+ RegisterNTPParsers();
RegisterTemplateParsers();
/** IMAP */
case ALPROTO_NFS:
proto_name = "nfs";
break;
+ case ALPROTO_NTP:
+ proto_name = "ntp";
+ break;
case ALPROTO_TEMPLATE:
proto_name = "template";
break;
ALPROTO_ENIP,
ALPROTO_DNP3,
ALPROTO_NFS,
+ ALPROTO_NTP,
ALPROTO_TEMPLATE,
/* used by the probing parser when alproto detection fails
# "detection-only" enables protocol detection only (parser disabled).
app-layer:
protocols:
+ ntp:
+ enabled: yes
nfs:
enabled: yes
tls: