1/*
2 * Copyright (c) 2015-2016, Intel Corporation
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Intel Corporation nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** \file
30 * \brief Declarations for the main NFA Engine API.
31 *
32 * This file provides the internal API for all runtime engines ("NFAs", even if
33 * they're not strictly NFA implementations).
34 */
35
36#ifndef NFA_API_H
37#define NFA_API_H
38
39#ifdef __cplusplus
40extern "C"
41{
42#endif
43
44#include "callback.h"
45#include "ue2common.h"
46
47struct mq;
48struct NFA;
49
50/**
51 * Indicates if an nfa is a zombie. Note: that there were plans for a more
52 * nuanced view of zombiehood but this never eventuated.
53 */
54enum nfa_zombie_status {
55 NFA_ZOMBIE_NO, /**< nfa is not a zombie and will respond to top events */
56 NFA_ZOMBIE_ALWAYS_YES /**< nfa is a zombie and will always be a zombie */
57};
58
59/**
60 * Compresses an engine's state.
61 * The expanded state (@ref mq::state, @ref mq::streamState) is reduced purely
62 * to a corresponding compressed stream state (@ref mq::streamState).
63 *
64 * @param nfa engine the state belongs to
65 * @param q queue for the engine. The final compressed stream stream is placed
66 * in the location indicated by @ref mq::streamState
67 * @param loc the location corresponding to the engine's current state
68 */
69char nfaQueueCompressState(const struct NFA *nfa, const struct mq *q, s64a loc);
70
71/**
72 * Expands an engine's compressed stream state, into its scratch space
73 * representation. This is required before an engine starts operating over its
74 * queue.
75 *
76 * @param nfa engine the state belongs to
77 * @param dest location in scratch for decompressed state
78 * @param src compressed stream state
79 * @param offset the current stream offset.
80 * @param key byte corresponding to the location where the compressed state was
81 * created.
82 */
83char nfaExpandState(const struct NFA *nfa, void *dest, const void *src,
84 u64a offset, u8 key);
85
86/**
87 * Gives us a properly initialised dead state suitable for later @ref
88 * nfaQueueExec calls.
89 */
90char nfaQueueInitState(const struct NFA *nfa, struct mq *q);
91
92/**
93 * Initialise the state, applying a TOP appropriate for the offset. If the
94 * NFA becomes inactive, return zero. Otherwise, write out its compressed
95 * representation to `state' and return non-zero.
96 *
97 * @param nfa engine the state belongs to
98 * @param offset offset in the stream (relative to start of stream)
99 * @param state pointer indicating where the state is to be written
100 * @param key byte corresponding to the location where the compressed state is
101 * to be created.
102 */
103char nfaInitCompressedState(const struct NFA *nfa, u64a offset, void *state,
104 u8 key);
105
106/**
107 * Process the queued commands on the given NFA.
108 *
109 * @param nfa the NFA to execute
110 * @param q the queued commands. It must start with some variant of start and
111 * end with some variant of end. The location field of the events must
112 * be monotonically increasing.
113 * @param end stop processing command queue when we reach this point
114 *
115 * @return non-zero if the nfa is still active, if the nfa is not active the
116 * state data is undefined
117 *
118 * Note: this function can not process events from the past: the location field
119 * of each event must be >= current offset.
120 */
121char nfaQueueExec(const struct NFA *nfa, struct mq *q, s64a end);
122
123/**
124 * Main execution function that doesn't perform the checks and optimisations of
125 * nfaQueueExec() and just dispatches directly to the nfa implementations. It is
126 * intended to be used by the Tamarama engine.
127 */
128char nfaQueueExec_raw(const struct NFA *nfa, struct mq *q, s64a end);
129
130/** Return value indicating that the engine is dead. */
131#define MO_DEAD 0
132
133/** Return value indicating that the engine is alive. */
134#define MO_ALIVE 1
135
136/** Return value from @ref nfaQueueExecToMatch indicating that engine progress
137 * stopped as a match state was reached. */
138#define MO_MATCHES_PENDING 2
139
140/**
141 * Process the queued commands on the given nfa up to end or the first match.
142 * This function will only fire the callback in response to an report_current
143 * being set and accepts at the starting offset, in all other situations accepts
144 * will result in the queue pausing with a return value of
145 * @ref MO_MATCHES_PENDING.
146 *
147 * @param nfa the NFA to execute
148 * @param q the queued commands. It must start with some variant of start and
149 * end with some variant of end. The location field of the events must
150 * be monotonically increasing. If not all the data was processed during
151 * the call, the queue is updated to reflect the remaining work.
152 * @param end stop processing command queue when we reach this point
153 *
154 * @return @ref MO_ALIVE if the nfa is still active with no matches pending,
155 * and @ref MO_MATCHES_PENDING if there are matches pending, 0 if not
156 * alive
157 *
158 * Note: if it can be determined that the stream can never match, the nfa
159 * may be reported as dead even if not all the data was scanned
160 *
161 * Note: if the nfa is not alive the state data is undefined
162 *
163 * Note: this function can not process events from the past: the location field
164 * of each event must be >= current offset.
165 */
166char nfaQueueExecToMatch(const struct NFA *nfa, struct mq *q, s64a end);
167
168/**
169 * Main execution function that doesn't perform the checks and optimisations of
170 * nfaQueueExecToMatch() and just dispatches directly to the nfa
171 * implementations. It is intended to be used by the Tamarama engine.
172 */
173char nfaQueueExec2_raw(const struct NFA *nfa, struct mq *q, s64a end);
174
175/**
176 * Report matches at the current queue location.
177 *
178 * @param nfa the NFA to execute
179 * @param q the queued commands. It must start with some variant of start and
180 * end with some variant of end. The location field of the events must
181 * be monotonically increasing.
182 *
183 * Note: the queue MUST be located at position where @ref nfaQueueExecToMatch
184 * returned @ref MO_MATCHES_PENDING.
185 *
186 * Note: the return value of this call is undefined, and should be ignored.
187 */
188char nfaReportCurrentMatches(const struct NFA *nfa, struct mq *q);
189
190/**
191 * Returns non-zero if the NFA is in an accept state with the given report ID.
192 */
193char nfaInAcceptState(const struct NFA *nfa, ReportID report, struct mq *q);
194
195/**
196 * Returns non-zero if the NFA is in any accept state regardless of report
197 * ID.
198 */
199char nfaInAnyAcceptState(const struct NFA *nfa, struct mq *q);
200
201/**
202 * Process the queued commands on the given NFA up to end or the first match.
203 *
204 * Note: This version is meant for rose prefix/infix NFAs:
205 * - never uses a callback
206 * - loading of state at a point in history is not special cased
207 *
208 * @param nfa the NFA to execute
209 * @param q the queued commands. It must start with some variant of start and
210 * end with some variant of end. The location field of the events must
211 * be monotonically increasing. If not all the data was processed during
212 * the call, the queue is updated to reflect the remaining work.
213 * @param report we are interested in. If the given report will be raised at
214 * the end location, the function returns @ref MO_MATCHES_PENDING. If no
215 * match information is desired, MO_INVALID_IDX should be passed in.
216 * @return @ref MO_ALIVE if the nfa is still active with no matches pending,
217 * and @ref MO_MATCHES_PENDING if there are matches pending, 0 if not
218 * alive
219 *
220 * Note: if it can be determined that the stream can never match, the nfa
221 * may be reported as dead even if not all the data was scanned
222 *
223 * Note: if the NFA is not active the state data is undefined.
224 */
225char nfaQueueExecRose(const struct NFA *nfa, struct mq *q, ReportID report);
226
227/**
228 * Runs an NFA in reverse from (buf + buflen) to buf and then from (hbuf + hlen)
229 * to hbuf (main buffer and history buffer).
230 *
231 * Note: provides the match location as the "end" offset when the callback is
232 * called.
233 *
234 * @param nfa engine to run
235 * @param offset base offset of buf
236 * @param buf main buffer
237 * @param buflen length of buf
238 * @param hbuf history buf
239 * @param hlen length of hbuf
240 * @param callback the callback to call for each match raised
241 * @param context context pointer passed to each callback
242 */
243char nfaBlockExecReverse(const struct NFA *nfa, u64a offset, const u8 *buf,
244 size_t buflen, const u8 *hbuf, size_t hlen,
245 NfaCallback callback, void *context);
246
247/**
248 * Check whether the given NFA's state indicates that it is in one or more
249 * final (accept at end of data) state. If so, call the callback for each
250 * match.
251 *
252 * @param nfa the NFA to execute
253 * @param state current state associated with this NFA
254 * @param streamState stream version of the state associated with this NFA
255 * (including br region)
256 * @param offset the offset to return (via the callback) with each match
257 * @param callback the callback to call for each match raised
258 * @param context context pointer passed to each callback
259 *
260 * @return @ref MO_HALT_MATCHING if the user instructed us to halt, otherwise
261 * @ref MO_CONTINUE_MATCHING.
262 */
263char nfaCheckFinalState(const struct NFA *nfa, const char *state,
264 const char *streamState, u64a offset,
265 NfaCallback callback, void *context);
266
267/**
268 * Indicates if an engine is a zombie.
269 *
270 * @param nfa engine to consider
271 * @param q queue corresponding to the engine
272 * @param loc current location in the buffer for an engine
273 */
274enum nfa_zombie_status nfaGetZombieStatus(const struct NFA *nfa, struct mq *q,
275 s64a loc);
276#ifdef __cplusplus
277} /* extern "C" */
278#endif
279
280#endif
281