1 /*
2  * Copyright (c) 2008-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_MSGMOD_H
18 #define NMSG_MSGMOD_H
19 
20 /*! \file nmsg/msgmod.h
21  * \brief Message modules.
22  *
23  * Message modules extend nmsg by allowing new message types to be implemented
24  * in dynamically loaded plugins. Msgmods identify the types of messages they
25  * can handle by registering a vendor ID number and a per-vendor message type
26  * number with the msgmod loader. Functions for creating and interpreting NMSG
27  * payloads must be provided.
28  *
29  * Msgmods are dynamically loaded shared objects that must provide either a
30  * symbol called <tt>nmsg_msgmod_ctx</tt> of type nmsg_msgmod or a symbol called
31  * <tt>nmsg_msgmod_ctx_array</tt> which will be interpreted as an array of
32  * pointers to objects of type struct nmsg_msgmod. If an array is used, the array
33  * must be terminated by a NULL pointer.
34  *
35  * The first field of the nmsg_msgmod structure is the version of the API between
36  * libnmsg and the extension module; module developers should use this header
37  * file for the struct nmsg_msgmod definition and assign this field the value
38  * #NMSG_MSGMOD_VERSION.
39  *
40  * Modules must be reentrant, as exported message handling functions may be
41  * called from multiple threads simultaneously.  An opaque pointer may be
42  * returned by the module initialization function; this pointer will be provided
43  * to module functions that require state and will be provided to the module
44  * finalization function for deallocation.
45  *
46  * If a message schema is restricted in a certain way, a C stub consisting of
47  * data definitions only can be used to interface with libnmsg.  This is called
48  * a "transparent module". Transparent modules are implemented using the
49  * Protobuf-C compiler.
50  *
51  * For an example of a transparent module, see the base/email message type in
52  * the nmsg distribution. The file <tt>nmsg/base/email.proto</tt> is compiled
53  * with the <a href="http://code.google.com/p/protobuf-c/">Protobuf-C
54  * compiler</a> into the files email.pb-c.c and email.pb-c.h. The file
55  * email.c provides the C stub to interface with the msgmod
56  * interface, which is compiled into a shared object and installed into the
57  * nmsg module directory.
58  *
59  * <b>MP:</b>
60  *	\li nmsg_msgmod_init() returns an opaque pointer which is used to
61  *	differentiate threads if a message module is not stateless.
62  */
63 
64 /**
65  * Enum mapping protocol buffer schema types to nmsg-specific types for
66  * "transparent" modules.
67  *
68  * Protocol buffers provide basic data types on which transparent message
69  * modules can build more meaningful types.
70  */
71 typedef enum {
72 	/** Protobuf enum. */
73 	nmsg_msgmod_ft_enum,
74 
75 	/** Protobuf byte array. */
76 	nmsg_msgmod_ft_bytes,
77 
78 	/**
79 	 * Protobuf byte array.
80 	 * String should not contain newlines.
81 	 */
82 	nmsg_msgmod_ft_string,
83 
84 	/**
85 	 * Protobuf byte array.
86 	 * String can contain newlines.
87 	 */
88 	nmsg_msgmod_ft_mlstring,
89 
90 	/**
91 	 * Protobuf byte array.
92 	 * Length must be 4 for IPv4 addresses or 16 for IPv6 addresses.
93 	 */
94 	nmsg_msgmod_ft_ip,
95 
96 	/** Protobuf uint32. */
97 	nmsg_msgmod_ft_uint16,
98 
99 	/** Protobuf uint32. */
100 	nmsg_msgmod_ft_uint32,
101 
102 	/** Protobuf uint64. */
103 	nmsg_msgmod_ft_uint64,
104 
105 	/** Protobuf int32. */
106 	nmsg_msgmod_ft_int16,
107 
108 	/** Protobuf int32. */
109 	nmsg_msgmod_ft_int32,
110 
111 	/** Protobuf int64. */
112 	nmsg_msgmod_ft_int64,
113 
114 	/** Protobuf double. */
115 	nmsg_msgmod_ft_double,
116 
117 	/** Protobuf bool. */
118 	nmsg_msgmod_ft_bool,
119 } nmsg_msgmod_field_type;
120 
121 #define NMSG_MSGMOD_FIELD_REPEATED      0x01	/*%< field is repeated */
122 #define NMSG_MSGMOD_FIELD_REQUIRED      0x02	/*%< field is required */
123 #define NMSG_MSGMOD_FIELD_HIDDEN        0x04	/*%< hide field from the message API */
124 #define NMSG_MSGMOD_FIELD_NOPRINT       0x08	/*%< don't print the field */
125 
126 /**
127  * Initialize a message module.
128  *
129  * \param[in] mod Initialized msgmod.
130  *
131  * \param[out] clos Opaque pointer specific to this instantiation of the module.
132  *	This pointer must be supplied to nmsg_msgmod functions taking a 'clos'
133  *	parameter.
134  *
135  * \return #nmsg_res_success
136  * \return #nmsg_res_failure
137  * \return #nmsg_res_memfail
138  * \return #nmsg_res_notimpl
139  */
140 nmsg_res
141 nmsg_msgmod_init(nmsg_msgmod_t mod, void **clos);
142 
143 /**
144  * Finalize a mesage module.
145  *
146  * \param[in] mod Initialized msgmod.
147  *
148  * \param[in] clos Opaque pointer returned by the module initialization
149  *	function.
150  *
151  * \return #nmsg_res_success
152  * \return #nmsg_res_failure
153  * \return #nmsg_res_notimpl
154  */
155 nmsg_res
156 nmsg_msgmod_fini(nmsg_msgmod_t mod, void **clos);
157 
158 /**
159  * Convert a presentation format line to an NMSG payload.
160  * Since the presentation format stream is line-delimited, not every line
161  * will necessarily result in a serialized message.
162  *
163  * When #nmsg_res_pbuf_ready is returned, the nmsg_msgmod_pres_to_payload_finalize()
164  * function should be used to obtain the serialized payload.
165  *
166  * Msgmods are not required to implement a function to convert presentation form
167  * data to payloads, in which case #nmsg_res_notimpl will be returned.
168  *
169  * \param[in] mod Initialized msgmod.
170  *
171  * \param[in] clos Opaque pointer returned by the module initialization
172  *	function.
173  *
174  * \param[in] pres Line of presentation form input of the type handled by 'mod'.
175  *
176  * \return #nmsg_res_success
177  * \return #nmsg_res_failure
178  * \return #nmsg_res_memfail
179  * \return #nmsg_res_notimpl
180  * \return #nmsg_res_parse_error
181  * \return #nmsg_res_pbuf_ready
182  */
183 nmsg_res
184 nmsg_msgmod_pres_to_payload(nmsg_msgmod_t mod, void *clos, const char *pres);
185 
186 /**
187  * After a call to nmsg_msgmod_pres_to_payload() returns #nmsg_res_pbuf_ready, this
188  * function will return the serialized payload. The caller is responsible for
189  * freeing the payload returned.
190  *
191  * \param[in] mod Initialized msgmod.
192  *
193  * \param[in] clos Opaque pointer returned by the module initialization
194  *	function.
195  *
196  * \param[out] pbuf Serialized payload.
197  *
198  * \param[out] sz Length of the serialized payload.
199  *
200  * \return #nmsg_res_success
201  * \return #nmsg_res_failure
202  * \return #nmsg_res_memfail
203  * \return #nmsg_res_notimpl
204  */
205 nmsg_res
206 nmsg_msgmod_pres_to_payload_finalize(nmsg_msgmod_t mod, void *clos, uint8_t **pbuf,
207 				     size_t *sz);
208 
209 /**
210  * Convert an IP datagram to an NMSG payload.
211  *
212  * Msgmods are not required to implement a function to convert IP datagrams to
213  * payloads, in which case #nmsg_res_notimpl will be returned.
214  *
215  * \param[in] mod Initialized msgmod.
216  *
217  * \param[in] clos Opaque pointer returned by the module initialization
218  *	function.
219  *
220  * \param[in] dg Filled nmsg_ipdg structure.
221  *
222  * \param[out] pbuf Serialized payload.
223  *
224  * \param[out] sz Length of the serialized payload.
225  *
226  * \return #nmsg_res_parse_error
227  * \return #nmsg_res_pbuf_ready
228  * \return #nmsg_res_notimpl
229  */
230 nmsg_res
231 nmsg_msgmod_ipdg_to_payload(nmsg_msgmod_t mod, void *clos,
232 			    const struct nmsg_ipdg *dg,
233 			    uint8_t **pbuf, size_t *sz);
234 
235 /**
236  * Read a raw packet and optionally convert it to an NMSG payload.
237  *
238  * Msgmods are not required to implement a function to convert raw packets to
239  * payloads, in which case #nmsg_res_notimpl will be returned.
240  *
241  * A message will only be consumable if the return value is #nmsg_res_success.
242  *
243  * \param[in] mod Initialized msgmod.
244  *
245  * \param[in] clos Opaque pointer returned by the module initialization
246  *	function.
247  *
248  * \param[in] pcap Pcap input to read packets from.
249  *
250  * \param[out] m Location to store payload.
251  *
252  * \return #nmsg_res_success
253  * \return #nmsg_res_again
254  * \return #nmsg_res_notimpl
255  */
256 nmsg_res
257 nmsg_msgmod_pkt_to_payload(struct nmsg_msgmod *mod, void *clos,
258 			   nmsg_pcap_t pcap, nmsg_message_t *m);
259 
260 /**
261  * Determine which nmsg_msgmod is responsible for a given vid/msgtype tuple,
262  * if any.
263  *
264  * \param[in] vid Numeric vendor ID.
265  *
266  * \param[in] msgtype Numeric message type.
267  *
268  * \return The nmsg_msgmod responsible for handling the given vid/msgtype tuple,
269  *	if such a module has been loaded into the set, or NULL otherwise.
270  */
271 nmsg_msgmod_t
272 nmsg_msgmod_lookup(unsigned vid, unsigned msgtype);
273 
274 /**
275  * Determine which nmsg_msgmod is responsible for a given vid/msgtype tuple,
276  * if any. This function looks up the vid and msgtype by name.
277  *
278  * \param[in] vname Vendor name.
279  *
280  * \param[in] mname Message type name.
281  *
282  * \return The nmsg_msgmod responsible for handling the given vid/msgtype tuple,
283  *	if such a module has been loaded into the set, or NULL otherwise.
284  */
285 nmsg_msgmod_t
286 nmsg_msgmod_lookup_byname(const char *vname, const char *mname);
287 
288 /**
289  * Convert the human-readable name of a message type to a message type ID.
290  *
291  * \param[in] vid Numeric vendor ID.
292  *
293  * \param[in] mname Message type name.
294  *
295  * \return A numeric message type ID. By convention, 0 is used to indicate an
296  *	unknown message type.
297  */
298 unsigned
299 nmsg_msgmod_mname_to_msgtype(unsigned vid, const char *mname);
300 
301 /**
302  * Convert a vendor ID / message type ID tuple to the human-readable form
303  * of the message type.
304  *
305  * \param[in] vid Numeric vendor ID.
306  *
307  * \param[in] msgtype Numeric message type.
308  *
309  * \return A human-readable message type name. NULL is returned if the vendor ID
310  *	or message type is unknown.
311  */
312 const char *
313 nmsg_msgmod_msgtype_to_mname(unsigned vid, unsigned msgtype);
314 
315 /**
316  * Convert a numeric vendor ID to its human-readable name.
317  *
318  * \param[in] vid Numeric vendor ID.
319  *
320  * \return A human-readable vendor name. NULL is returned if the vendor ID is
321  *	unknown.
322  */
323 const char *
324 nmsg_msgmod_vid_to_vname(unsigned vid);
325 
326 /**
327  * Convert a human-readable vendor name to its numeric ID.
328  *
329  * \param[in] vname Vendor name.
330  *
331  * \return A numeric vendor ID. By convention, 0 is used to indicate an unknown
332  *	vendor ID.
333  */
334 unsigned
335 nmsg_msgmod_vname_to_vid(const char *vname);
336 
337 /**
338  * Return the maximum vendor ID.
339  */
340 unsigned
341 nmsg_msgmod_get_max_vid(void);
342 
343 /**
344  * Return the maximum message type registered to a vendor ID.
345  *
346  * \param[in] vid Numeric vendor ID.
347  */
348 unsigned
349 nmsg_msgmod_get_max_msgtype(unsigned vid);
350 
351 #endif /* NMSG_MSGMOD_H */
352