1 /*
2  * Copyright (c) 2015 by Farsight Security, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef NMSG_FLTMOD_PLUGIN_H
18 #define NMSG_FLTMOD_PLUGIN_H
19 
20 /*! \file nmsg/fltmod_plugin.h
21  * \brief Implementing message filter modules.
22  *
23  * This file defines the interface that developers of message filter modules
24  * must implement. For the interface for loading and calling filter modules,
25  * see nmsg/fltmod.h.
26  *
27  * Filter modules are dynamically loaded shared objects that must export a
28  * symbol called <tt>nmsg_fltmod_plugin_export</tt>. This is a structure of
29  * type #nmsg_fltmod_plugin and is the sole entry point into the module.
30  *
31  * The first field of the nmsg_fltmod_plugin structure is the version of the
32  * API/ABI between libnmsg and the filter module. Module developers should
33  * assign this field the value #NMSG_FLTMOD_VERSION, or they can add
34  * <tt>NMSG_FLTMOD_REQUIRED_INIT,</tt> to the initializer, which is a
35  * convenience macro that initializes required fields.
36  *
37  * A filter module needs to provide at least one function, the core message
38  * filtering function <tt>filter_message</tt>. This function must be
39  * thread-safe, since it may be called simultaneously from multiple threads.
40  *
41  * Optionally, up to four more functions may be provided: a global module
42  * initializer and finalizer (<tt>module_init</tt> and <tt>module_fini</tt>),
43  * and a per-thread initializer and finalizer (<tt>thread_init</tt> and
44  * <tt>thread_fini</tt>). These functions can be used to acquire and release
45  * resources, generate debug messages, etc. The module and thread initializers
46  * may provide opaque data pointers. These pointers will be provided as
47  * parameters to the message filtering function.
48  *
49  * The <tt>module_init</tt> function will only be called once, immediately
50  * after the plugin module has been loaded. It will be called before all other
51  * module functions. Therefore, it does not need to be thread-safe.
52  *
53  * The <tt>module_fini</tt> function will only be called once, immediately
54  * before the plugin module will be unloaded from the process. It will be
55  * called after all other module functions. Therefore, it does not need to be
56  * thread-safe, either.
57  *
58  * The <tt>thread_init</tt> and <tt>thread_fini</tt> functions may be called by
59  * a processing thread after the thread has started and before the thread
60  * exits. They need to be thread-safe, since they be called by independently
61  * executing threads. A thread may not call a module's <tt>filter_message</tt>
62  * function before it has called <tt>thread_init</tt>, and it may not call
63  * <tt>filter_message</tt> after it has called <tt>thread_fini</tt>.
64  *
65  * For an example of a simple message filtering module, see the "sample" filter
66  * module in the fltmod/ directory of the nmsg distribution. The "sample"
67  * filter performs either systematic count-based or uniform probabilistic
68  * sampling of the message stream.
69  */
70 
71 #include <nmsg.h>
72 
73 /** Version number of the nmsg fltmod ABI. */
74 #define NMSG_FLTMOD_VERSION	1
75 
76 /**
77  * Initialize the filter module.
78  *
79  * Data with module-defined meaning may be passed in via the 'param' and
80  * 'len_param' parameters. This can be used to, for example, configure
81  * module-specific filtering parameters.
82  *
83  * \param[in] param
84  *	Module-defined data needed for the initialization of the module.
85  *
86  * \param[in] len_param
87  *	Length of 'param'.
88  *
89  * \param[out] mod_data
90  *	Module-defined, module-wide state, passed to other module functions
91  *	that take a 'mod_data' parameter.
92  *
93  * \return #nmsg_res_success
94  *	If the module was successfully initialized.
95  * \return
96  *	Any other result to indicate a fatal error.
97  */
98 typedef nmsg_res
99 (*nmsg_fltmod_module_init_fp)(const void *param,
100 			      const size_t len_param,
101 			      void **mod_data);
102 
103 /**
104  * Destroy the filter module. Any module-wide resources acquired by the module
105  * must be released.
106  *
107  * \param[in] mod_data
108  *	Module-defined, module-wide state.
109  */
110 typedef void
111 (*nmsg_fltmod_module_fini_fp)(void *mod_data);
112 
113 /**
114  * Initialize module-defined, thread-wide state.
115  *
116  * \param[in] mod_data
117  *	Module-defined, module-wide state.
118  *
119  * \param[out] thr_data
120  *	Module-defined, thread-wide state.
121  *
122  * \return #nmsg_res_success
123  *	If the thread-wide state was successfully initialized.
124  * \return
125  *	Any other result to indicate a fatal error.
126  */
127 typedef nmsg_res
128 (*nmsg_fltmod_thread_init_fp)(void *mod_data, void **thr_data);
129 
130 /**
131  * Destroy thread-wide state. Any thread-wide resources corresponding to the
132  * passed in 'thr_data' value that have been acquired by the module must be
133  * released.
134  *
135  * \param[in] mod_data
136  *	Module-defined, module-wide state.
137  *
138  * \param[in] thr_data
139  *	Module-defined, thread-wide state.
140  *
141  * \return #nmsg_res_success
142  *	If the thread-wide state was successfully destroyed.
143  * \return
144  *	Any other result to indicate a fatal error.
145  */
146 typedef nmsg_res
147 (*nmsg_fltmod_thread_fini_fp)(void *mod_data, void *thr_data);
148 
149 /**
150  * Filter a message object and return the filter verdict.
151  *
152  * The filter function may alter the message object, or it may replace the
153  * message object with an entirely new message. If the filter function replaces
154  * the message object, it is responsible for disposing of the old message, for
155  * instance by calling nmsg_message_destroy().
156  *
157  * \param[in,out] msg
158  *	Pointer to the message object to be filtered. The message object may
159  *	optionally be altered, or it may be replaced with an entirely new
160  *	message object.
161  *
162  * \param[in] mod_data
163  *	Module-defined, module-wide state.
164  *
165  * \param[in] thr_data
166  *	Module-defined, thread-wide state.
167  *
168  * \param[out] vres
169  *	The filter verdict. \see #nmsg_filter_message_verdict for the possible
170  *	verdict results and meanings.
171  *
172  * \return #nmsg_res_success
173  *      The filtering completed and returned a verdict in 'vres'.
174  * \return
175  *	Any other result to indicate a fatal error.
176  */
177 typedef nmsg_res
178 (*nmsg_fltmod_filter_message_fp)(nmsg_message_t *msg,
179 				 void *mod_data,
180 				 void *thr_data,
181 				 nmsg_filter_message_verdict *vres);
182 
183 /** Convenience macro. */
184 #define NMSG_FLTMOD_REQUIRED_INIT \
185 	.fltmod_version = NMSG_FLTMOD_VERSION
186 
187 /**
188  * Structure exported by filter modules.
189  */
190 struct nmsg_fltmod_plugin {
191 	/**
192 	 * Module interface version.
193 	 * Must be set to #NMSG_FLTMOD_VERSION or the module will be rejected
194 	 * at load time.
195 	 */
196 	long					fltmod_version;
197 
198 	/**
199 	 * Module-wide initialization function. Optional, may be NULL. If this
200 	 * function exists, it will be called once at module startup by
201 	 * nmsg_fltmod_init().
202 	 */
203 	nmsg_fltmod_module_init_fp		module_init;
204 
205 	/**
206 	 * Module-wide finalization function. Optional, may be NULL. If this
207 	 * function exists, it will be called once at module shutdown by
208 	 * nmsg_fltmod_destroy(). This function should clean up any resources
209 	 * acquired by 'module_init'.
210 	 */
211 	nmsg_fltmod_module_fini_fp		module_fini;
212 
213 	/**
214 	 * Per-thread initialization function. Optional, may be NULL. If this
215 	 * function exists, it will be called by each thread that wants to
216 	 * perform message filtering via nmsg_fltmod_thread_init().
217 	 */
218 	nmsg_fltmod_thread_init_fp		thread_init;
219 
220 	/**
221 	 * Per-thread finalization function. Optional, may be NULL. If this
222 	 * function exists, it will be called by each thread that has called
223 	 * 'thread_init' before the thread exits by nmsg_fltmod_thread_fini().
224 	 * This function should clean up any resources acquired by
225 	 * 'thread_init'.
226 	 */
227 	nmsg_fltmod_thread_fini_fp		thread_fini;
228 
229 	/**
230 	 * Message filter function. Required, must not be NULL. This function
231 	 * is called by nmsg_fltmod_filter_message().
232 	 */
233 	nmsg_fltmod_filter_message_fp		filter_message;
234 
235 	/**
236 	 * \private Reserved fields.
237 	 */
238 	void					*_reserved15;
239 	void					*_reserved14;
240 	void					*_reserved13;
241 	void					*_reserved12;
242 	void					*_reserved11;
243 	void					*_reserved10;
244 	void					*_reserved9;
245 	void					*_reserved8;
246 	void					*_reserved7;
247 	void					*_reserved6;
248 	void					*_reserved5;
249 	void					*_reserved4;
250 	void					*_reserved3;
251 	void					*_reserved2;
252 	void					*_reserved1;
253 	void					*_reserved0;
254 };
255 
256 #endif /* NMSG_FLTMOD_PLUGIN_H */
257