Initial OpenECOMP Demo commit
[demo.git] / vnfs / VES / code / evel_library / evel_syslog.c
1 /**************************************************************************//**
2  * @file
3  * Implementation of EVEL functions relating to the Syslog.
4  *
5  * License
6  * -------
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:  This product includes
18  *    software developed by the AT&T.
19  * 4. Neither the name of AT&T nor the names of its contributors may be used to
20  *    endorse or promote products derived from this software without specific
21  *    prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
24  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
27  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *****************************************************************************/
34
35 #include <string.h>
36 #include <assert.h>
37 #include <stdlib.h>
38
39 #include "evel_throttle.h"
40
41 /**************************************************************************//**
42  * Create a new Syslog event.
43  *
44  * @note    The mandatory fields on the Syslog must be supplied to this factory
45  *          function and are immutable once set.  Optional fields have explicit
46  *          setter functions, but again values may only be set once so that the
47  *          Syslog has immutable properties.
48  * @param   event_source_type  The type of Syslog event source.
49  * @param   syslog_msg         The Syslog event message.
50  * @param   syslog_tag         The messgaeId identifying the type of message.
51  * @returns pointer to the newly manufactured ::EVENT_SYSLOG.  If the event is
52  *          not used (i.e. posted) it must be released using
53  *          ::evel_free_syslog.
54  * @retval  NULL  Failed to create the event.
55  *****************************************************************************/
56 EVENT_SYSLOG * evel_new_syslog(EVEL_SOURCE_TYPES event_source_type,
57                                const char * const syslog_msg,
58                                const char * const syslog_tag)
59 {
60   EVENT_SYSLOG * syslog = NULL;
61   EVEL_ENTER();
62
63   /***************************************************************************/
64   /* Check preconditions.                                                    */
65   /***************************************************************************/
66   assert(event_source_type < EVEL_MAX_SOURCE_TYPES);
67   assert(syslog_msg != NULL);
68   assert(syslog_tag != NULL);
69
70   /***************************************************************************/
71   /* Allocate the Syslog.                                                    */
72   /***************************************************************************/
73   syslog = malloc(sizeof(EVENT_SYSLOG));
74   if (syslog == NULL)
75   {
76     log_error_state("Out of memory");
77     goto exit_label;
78   }
79   memset(syslog, 0, sizeof(EVENT_SYSLOG));
80   EVEL_DEBUG("New Syslog is at %lp", syslog);
81
82   /***************************************************************************/
83   /* Initialize the header & the Syslog fields.  Optional string values are  */
84   /* uninitialized (NULL).                                                   */
85   /***************************************************************************/
86   evel_init_header(&syslog->header);
87   syslog->header.event_domain = EVEL_DOMAIN_SYSLOG;
88   syslog->major_version = EVEL_SYSLOG_MAJOR_VERSION;
89   syslog->minor_version = EVEL_SYSLOG_MINOR_VERSION;
90   syslog->event_source_type = event_source_type;
91   syslog->syslog_msg = strdup(syslog_msg);
92   syslog->syslog_tag = strdup(syslog_tag);
93   dlist_initialize(&syslog->additional_fields);
94   evel_init_option_int(&syslog->syslog_facility);
95   evel_init_option_int(&syslog->syslog_proc_id);
96   evel_init_option_int(&syslog->syslog_ver);
97   evel_init_option_string(&syslog->event_source_host);
98   evel_init_option_string(&syslog->syslog_proc);
99   evel_init_option_string(&syslog->syslog_s_data);
100
101 exit_label:
102   EVEL_EXIT();
103   return syslog;
104 }
105
106 /**************************************************************************//**
107  * Set the Event Type property of the Syslog.
108  *
109  * @note  The property is treated as immutable: it is only valid to call
110  *        the setter once.  However, we don't assert if the caller tries to
111  *        overwrite, just ignoring the update instead.
112  *
113  * @param syslog      Pointer to the syslog.
114  * @param type        The Event Type to be set. ASCIIZ string. The caller
115  *                    does not need to preserve the value once the function
116  *                    returns.
117  *****************************************************************************/
118 void evel_syslog_type_set(EVENT_SYSLOG * syslog,
119                           const char * const type)
120 {
121   EVEL_ENTER();
122
123   /***************************************************************************/
124   /* Check preconditions and call evel_header_type_set.                      */
125   /***************************************************************************/
126   assert(syslog != NULL);
127   assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
128   evel_header_type_set(&syslog->header, type);
129
130   EVEL_EXIT();
131 }
132
133 /**************************************************************************//**
134  * Add an additional value name/value pair to the Syslog.
135  *
136  * The name and value are null delimited ASCII strings.  The library takes
137  * a copy so the caller does not have to preserve values after the function
138  * returns.
139  *
140  * @param syslog    Pointer to the syslog.
141  * @param name      ASCIIZ string with the attribute's name.  The caller
142  *                  does not need to preserve the value once the function
143  *                  returns.
144  * @param value     ASCIIZ string with the attribute's value.  The caller
145  *                  does not need to preserve the value once the function
146  *                  returns.
147  *****************************************************************************/
148 void evel_syslog_addl_field_add(EVENT_SYSLOG * syslog,
149                                 char * name,
150                                 char * value)
151 {
152   SYSLOG_ADDL_FIELD * addl_field = NULL;
153   EVEL_ENTER();
154
155   /***************************************************************************/
156   /* Check preconditions.                                                    */
157   /***************************************************************************/
158   assert(syslog != NULL);
159   assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
160   assert(name != NULL);
161   assert(value != NULL);
162
163   EVEL_DEBUG("Adding name=%s value=%s", name, value);
164   addl_field = malloc(sizeof(SYSLOG_ADDL_FIELD));
165   assert(addl_field != NULL);
166   memset(addl_field, 0, sizeof(SYSLOG_ADDL_FIELD));
167   addl_field->name = strdup(name);
168   addl_field->value = strdup(value);
169   assert(addl_field->name != NULL);
170   assert(addl_field->value != NULL);
171
172   dlist_push_last(&syslog->additional_fields, addl_field);
173
174   EVEL_EXIT();
175 }
176
177 /**************************************************************************//**
178  * Set the Event Source Host property of the Syslog.
179  *
180  * @note  The property is treated as immutable: it is only valid to call
181  *        the setter once.  However, we don't assert if the caller tries to
182  *        overwrite, just ignoring the update instead.
183  *
184  * @param syslog     Pointer to the Syslog.
185  * @param host       The Event Source Host to be set. ASCIIZ string. The caller
186  *                   does not need to preserve the value once the function
187  *                   returns.
188  *****************************************************************************/
189 void evel_syslog_event_source_host_set(EVENT_SYSLOG * syslog,
190                                        const char * const host)
191 {
192   EVEL_ENTER();
193
194   /***************************************************************************/
195   /* Check preconditions.                                                    */
196   /***************************************************************************/
197   assert(syslog != NULL);
198   assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
199   assert(host != NULL);
200
201   evel_set_option_string(&syslog->event_source_host,
202                          host,
203                          "Event Source Host");
204   EVEL_EXIT();
205 }
206
207 /**************************************************************************//**
208  * Set the Facility property of the Syslog.
209  *
210  * @note  The property is treated as immutable: it is only valid to call
211  *        the setter once.  However, we don't assert if the caller tries to
212  *        overwrite, just ignoring the update instead.
213  *
214  * @param syslog      Pointer to the Syslog.
215  * @param facility    The Syslog Facility to be set.  ASCIIZ string. The caller
216  *                    does not need to preserve the value once the function
217  *                    returns.
218  *****************************************************************************/
219 void evel_syslog_facility_set(EVENT_SYSLOG * syslog,
220                               EVEL_SYSLOG_FACILITIES facility)
221 {
222   EVEL_ENTER();
223
224   /***************************************************************************/
225   /* Check preconditions.                                                    */
226   /***************************************************************************/
227   assert(syslog != NULL);
228   assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
229   assert(facility < EVEL_MAX_SYSLOG_FACILITIES);
230
231   evel_set_option_int(&syslog->syslog_facility,
232                       facility,
233                       "Facility");
234   EVEL_EXIT();
235 }
236
237 /**************************************************************************//**
238  * Set the Process property of the Syslog.
239  *
240  * @note  The property is treated as immutable: it is only valid to call
241  *        the setter once.  However, we don't assert if the caller tries to
242  *        overwrite, just ignoring the update instead.
243  *
244  * @param syslog     Pointer to the Syslog.
245  * @param proc       The Process to be set. ASCIIZ string. The caller does not
246  *                   need to preserve the value once the function returns.
247  *****************************************************************************/
248 void evel_syslog_proc_set(EVENT_SYSLOG * syslog, const char * const proc)
249 {
250   EVEL_ENTER();
251
252   /***************************************************************************/
253   /* Check preconditions.                                                    */
254   /***************************************************************************/
255   assert(syslog != NULL);
256   assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
257   assert(proc != NULL);
258
259   evel_set_option_string(&syslog->syslog_proc, proc, "Process");
260   EVEL_EXIT();
261 }
262
263 /**************************************************************************//**
264  * Set the Process ID property of the Syslog.
265  *
266  * @note  The property is treated as immutable: it is only valid to call
267  *        the setter once.  However, we don't assert if the caller tries to
268  *        overwrite, just ignoring the update instead.
269  *
270  * @param syslog     Pointer to the Syslog.
271  * @param proc_id    The Process ID to be set. ASCIIZ string. The caller does
272  *                   not need to preserve the value once the function returns.
273  *****************************************************************************/
274 void evel_syslog_proc_id_set(EVENT_SYSLOG * syslog, int proc_id)
275 {
276   EVEL_ENTER();
277
278   /***************************************************************************/
279   /* Check preconditions.                                                    */
280   /***************************************************************************/
281   assert(syslog != NULL);
282   assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
283   assert(proc_id > 0);
284
285   evel_set_option_int(&syslog->syslog_proc_id,
286                       proc_id,
287                       "Process ID");
288   EVEL_EXIT();
289 }
290
291 /**************************************************************************//**
292  * Set the Version property of the Syslog.
293  *
294  * @note  The property is treated as immutable: it is only valid to call
295  *        the setter once.  However, we don't assert if the caller tries to
296  *        overwrite, just ignoring the update instead.
297  *
298  * @param syslog     Pointer to the Syslog.
299  * @param version    The Version to be set. ASCIIZ string. The caller does not
300  *                   need to preserve the value once the function returns.
301  *****************************************************************************/
302 void evel_syslog_version_set(EVENT_SYSLOG * syslog, int version)
303 {
304   EVEL_ENTER();
305
306   /***************************************************************************/
307   /* Check preconditions.                                                    */
308   /***************************************************************************/
309   assert(syslog != NULL);
310   assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
311   assert(version >= 0);
312
313   evel_set_option_int(&syslog->syslog_ver,
314                       version,
315                       "Version");
316   EVEL_EXIT();
317 }
318
319 /**************************************************************************//**
320  * Set the Structured Data property of the Syslog.
321  *
322  * @note  The property is treated as immutable: it is only valid to call
323  *        the setter once.  However, we don't assert if the caller tries to
324  *        overwrite, just ignoring the update instead.
325  *
326  * @param syslog     Pointer to the Syslog.
327  * @param s_data     The Structured Data to be set. ASCIIZ string. The caller
328  *                   does not need to preserve the value once the function
329  *                   returns.
330  *****************************************************************************/
331 void evel_syslog_s_data_set(EVENT_SYSLOG * syslog, const char * const s_data)
332 {
333   EVEL_ENTER();
334
335   /***************************************************************************/
336   /* Check preconditions.                                                    */
337   /***************************************************************************/
338   assert(syslog != NULL);
339   assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
340   assert(s_data != NULL);
341
342   evel_set_option_string(&syslog->syslog_s_data,
343                          s_data,
344                          "Structured Data");
345   EVEL_EXIT();
346 }
347
348 /**************************************************************************//**
349  * Encode the Syslog in JSON according to AT&T's schema for the event type.
350  *
351  * @param jbuf          Pointer to the ::EVEL_JSON_BUFFER to encode into.
352  * @param event         Pointer to the ::EVENT_HEADER to encode.
353  *****************************************************************************/
354 void evel_json_encode_syslog(EVEL_JSON_BUFFER * jbuf,
355                              EVENT_SYSLOG * event)
356 {
357   char * event_source_type;
358   SYSLOG_ADDL_FIELD * addl_field = NULL;
359   DLIST_ITEM * addl_field_item = NULL;
360
361   EVEL_ENTER();
362
363   /***************************************************************************/
364   /* Check preconditions.                                                    */
365   /***************************************************************************/
366   assert(event != NULL);
367   assert(event->header.event_domain == EVEL_DOMAIN_SYSLOG);
368
369   event_source_type = evel_source_type(event->event_source_type);
370
371   evel_json_encode_header(jbuf, &event->header);
372   evel_json_open_named_object(jbuf, "syslogFields");
373
374   /***************************************************************************/
375   /* Mandatory fields                                                        */
376   /***************************************************************************/
377   evel_enc_kv_string(jbuf, "eventSourceType", event_source_type);
378   evel_enc_kv_string(jbuf, "syslogMsg", event->syslog_msg);
379   evel_enc_kv_string(jbuf, "syslogTag", event->syslog_tag);
380   evel_enc_version(
381     jbuf, "syslogFieldsVersion", event->major_version, event->minor_version);
382
383   /***************************************************************************/
384   /* Optional fields                                                         */
385   /***************************************************************************/
386   evel_json_checkpoint(jbuf);
387   if (evel_json_open_opt_named_list(jbuf, "additionalFields"))
388   {
389     bool item_added = false;
390
391     addl_field_item = dlist_get_first(&event->additional_fields);
392     while (addl_field_item != NULL)
393     {
394       addl_field = (SYSLOG_ADDL_FIELD *) addl_field_item->item;
395       assert(addl_field != NULL);
396
397       if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
398                                           "additionalFields",
399                                           addl_field->name))
400       {
401         evel_json_open_object(jbuf);
402         evel_enc_kv_string(jbuf, "name", addl_field->name);
403         evel_enc_kv_string(jbuf, "value", addl_field->value);
404         evel_json_close_object(jbuf);
405         item_added = true;
406       }
407       addl_field_item = dlist_get_next(addl_field_item);
408     }
409     evel_json_close_list(jbuf);
410
411     /*************************************************************************/
412     /* If we've not written anything, rewind to before we opened the list.   */
413     /*************************************************************************/
414     if (!item_added)
415     {
416       evel_json_rewind(jbuf);
417     }
418   }
419
420   evel_enc_kv_opt_string(jbuf, "eventSourceHost", &event->event_source_host);
421   evel_enc_kv_opt_int(jbuf, "syslogFacility", &event->syslog_facility);
422   evel_enc_kv_opt_string(jbuf, "syslogProc", &event->syslog_proc);
423   evel_enc_kv_opt_int(jbuf, "syslogProcId", &event->syslog_proc_id);
424   evel_enc_kv_opt_string(jbuf, "syslogSData", &event->syslog_s_data);
425   evel_enc_kv_opt_int(jbuf, "syslogVer", &event->syslog_ver);
426   evel_json_close_object(jbuf);
427
428   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_KERNEL == 0);
429   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_USER == 1);
430   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_MAIL == 2);
431   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_SYSTEM_DAEMON == 3);
432   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_SECURITY_AUTH == 4);
433   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_INTERNAL == 5);
434   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LINE_PRINTER == 6);
435   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_NETWORK_NEWS == 7);
436   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_UUCP == 8);
437   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_CLOCK_DAEMON == 9);
438   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_SECURITY_AUTH2 == 10);
439   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_FTP_DAEMON == 11);
440   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_NTP == 12);
441   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOG_AUDIT == 13);
442   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOG_ALERT == 14);
443   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_CLOCK_DAEMON2 == 15);
444   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL0 == 16);
445   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL1 == 17);
446   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL2 == 18);
447   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL3 == 19);
448   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL4 == 20);
449   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL5 == 21);
450   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL6 == 22);
451   EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL7 == 23);
452
453   EVEL_EXIT();
454 }
455
456 /**************************************************************************//**
457  * Free a Syslog.
458  *
459  * Free off the Syslog supplied.  Will free all the contained allocated memory.
460  *
461  * @note It does not free the Syslog itself, since that may be part of a
462  * larger structure.
463  *****************************************************************************/
464 void evel_free_syslog(EVENT_SYSLOG * event)
465 {
466   SYSLOG_ADDL_FIELD * addl_field = NULL;
467
468   EVEL_ENTER();
469
470   /***************************************************************************/
471   /* Check preconditions.  As an internal API we don't allow freeing NULL    */
472   /* events as we do on the public API.                                      */
473   /***************************************************************************/
474   assert(event != NULL);
475   assert(event->header.event_domain == EVEL_DOMAIN_SYSLOG);
476
477   /***************************************************************************/
478   /* Free all internal strings then the header itself.                       */
479   /***************************************************************************/
480   addl_field = dlist_pop_last(&event->additional_fields);
481   while (addl_field != NULL)
482   {
483     EVEL_DEBUG("Freeing Additional Field (%s, %s)",
484                addl_field->name,
485                addl_field->value);
486     free(addl_field->name);
487     free(addl_field->value);
488     free(addl_field);
489     addl_field = dlist_pop_last(&event->additional_fields);
490   }
491
492   evel_free_option_string(&event->event_source_host);
493   free(event->syslog_msg);
494   evel_free_option_string(&event->syslog_proc);
495   evel_free_option_string(&event->syslog_s_data);
496   free(event->syslog_tag);
497   evel_free_header(&event->header);
498
499   EVEL_EXIT();
500 }