1 /**************************************************************************//**
3 * Implementation of EVEL functions relating to the Syslog.
8 * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
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
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 *****************************************************************************/
26 #include "evel_throttle.h"
28 /**************************************************************************//**
29 * Create a new Syslog event.
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
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)
47 EVENT_SYSLOG * syslog = NULL;
50 /***************************************************************************/
51 /* Check preconditions. */
52 /***************************************************************************/
53 assert(event_source_type < EVEL_MAX_SOURCE_TYPES);
54 assert(syslog_msg != NULL);
55 assert(syslog_tag != NULL);
57 /***************************************************************************/
58 /* Allocate the Syslog. */
59 /***************************************************************************/
60 syslog = malloc(sizeof(EVENT_SYSLOG));
63 log_error_state("Out of memory");
66 memset(syslog, 0, sizeof(EVENT_SYSLOG));
67 EVEL_DEBUG("New Syslog is at %lp", syslog);
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);
93 /**************************************************************************//**
94 * Set the Event Type property of the Syslog.
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.
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
104 *****************************************************************************/
105 void evel_syslog_type_set(EVENT_SYSLOG * syslog,
106 const char * const type)
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);
120 /**************************************************************************//**
121 * Add an additional value name/value pair to the Syslog.
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
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
131 * @param value ASCIIZ string with the attribute's value. The caller
132 * does not need to preserve the value once the function
134 *****************************************************************************/
135 void evel_syslog_addl_field_add(EVENT_SYSLOG * syslog,
139 SYSLOG_ADDL_FIELD * addl_field = NULL;
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);
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);
159 dlist_push_last(&syslog->additional_fields, addl_field);
164 /**************************************************************************//**
165 * Set the Event Source Host property of the Syslog.
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.
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
175 *****************************************************************************/
176 void evel_syslog_event_source_host_set(EVENT_SYSLOG * syslog,
177 const char * const host)
181 /***************************************************************************/
182 /* Check preconditions. */
183 /***************************************************************************/
184 assert(syslog != NULL);
185 assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
186 assert(host != NULL);
188 evel_set_option_string(&syslog->event_source_host,
190 "Event Source Host");
194 /**************************************************************************//**
195 * Set the Facility property of the Syslog.
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.
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
205 *****************************************************************************/
206 void evel_syslog_facility_set(EVENT_SYSLOG * syslog,
207 EVEL_SYSLOG_FACILITIES facility)
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);
218 evel_set_option_int(&syslog->syslog_facility,
224 /**************************************************************************//**
225 * Set the Process property of the Syslog.
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.
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)
239 /***************************************************************************/
240 /* Check preconditions. */
241 /***************************************************************************/
242 assert(syslog != NULL);
243 assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
244 assert(proc != NULL);
246 evel_set_option_string(&syslog->syslog_proc, proc, "Process");
250 /**************************************************************************//**
251 * Set the Process ID property of the Syslog.
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.
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)
265 /***************************************************************************/
266 /* Check preconditions. */
267 /***************************************************************************/
268 assert(syslog != NULL);
269 assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
272 evel_set_option_int(&syslog->syslog_proc_id,
278 /**************************************************************************//**
279 * Set the Version property of the Syslog.
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.
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)
293 /***************************************************************************/
294 /* Check preconditions. */
295 /***************************************************************************/
296 assert(syslog != NULL);
297 assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
298 assert(version >= 0);
300 evel_set_option_int(&syslog->syslog_ver,
306 /**************************************************************************//**
307 * Set the Structured Data property of the Syslog.
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.
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
317 *****************************************************************************/
318 void evel_syslog_s_data_set(EVENT_SYSLOG * syslog, const char * const s_data)
322 /***************************************************************************/
323 /* Check preconditions. */
324 /***************************************************************************/
325 assert(syslog != NULL);
326 assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
327 assert(s_data != NULL);
329 evel_set_option_string(&syslog->syslog_s_data,
335 /**************************************************************************//**
336 * Encode the Syslog in JSON according to AT&T's schema for the event type.
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)
344 char * event_source_type;
345 SYSLOG_ADDL_FIELD * addl_field = NULL;
346 DLIST_ITEM * addl_field_item = NULL;
350 /***************************************************************************/
351 /* Check preconditions. */
352 /***************************************************************************/
353 assert(event != NULL);
354 assert(event->header.event_domain == EVEL_DOMAIN_SYSLOG);
356 event_source_type = evel_source_type(event->event_source_type);
358 evel_json_encode_header(jbuf, &event->header);
359 evel_json_open_named_object(jbuf, "syslogFields");
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);
368 jbuf, "syslogFieldsVersion", event->major_version, event->minor_version);
370 /***************************************************************************/
371 /* Optional fields */
372 /***************************************************************************/
373 evel_json_checkpoint(jbuf);
374 if (evel_json_open_opt_named_list(jbuf, "additionalFields"))
376 bool item_added = false;
378 addl_field_item = dlist_get_first(&event->additional_fields);
379 while (addl_field_item != NULL)
381 addl_field = (SYSLOG_ADDL_FIELD *) addl_field_item->item;
382 assert(addl_field != NULL);
384 if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
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);
394 addl_field_item = dlist_get_next(addl_field_item);
396 evel_json_close_list(jbuf);
398 /*************************************************************************/
399 /* If we've not written anything, rewind to before we opened the list. */
400 /*************************************************************************/
403 evel_json_rewind(jbuf);
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);
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);
443 /**************************************************************************//**
446 * Free off the Syslog supplied. Will free all the contained allocated memory.
448 * @note It does not free the Syslog itself, since that may be part of a
450 *****************************************************************************/
451 void evel_free_syslog(EVENT_SYSLOG * event)
453 SYSLOG_ADDL_FIELD * addl_field = NULL;
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);
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)
470 EVEL_DEBUG("Freeing Additional Field (%s, %s)",
473 free(addl_field->name);
474 free(addl_field->value);
476 addl_field = dlist_pop_last(&event->additional_fields);
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);