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