Wed Jan 8 2020 09:49:42

Asterisk developer's documentation


cdr_syslog.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2009, malleable, LLC.
5  *
6  * Sean Bright <sean@malleable.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*!
20  * \file
21  * \brief syslog CDR logger
22  *
23  * \author Sean Bright <sean@malleable.com>
24  *
25  * See also
26  * \arg \ref Config_cdr
27  * \ingroup cdr_drivers
28  */
29 
30 /*** MODULEINFO
31  <depend>syslog</depend>
32  <support_level>core</support_level>
33 ***/
34 
35 #include "asterisk.h"
36 
37 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 337973 $")
38 
39 #include "asterisk/module.h"
40 #include "asterisk/lock.h"
41 #include "asterisk/cdr.h"
42 #include "asterisk/pbx.h"
43 
44 #include <syslog.h>
45 
46 #include "asterisk/syslog.h"
47 
48 static const char CONFIG[] = "cdr_syslog.conf";
49 
51 
52 static const char name[] = "cdr-syslog";
53 
54 struct cdr_config {
58  );
59  int facility;
60  int priority;
63 };
64 
66 
67 static void free_config(void)
68 {
69  struct cdr_config *sink;
70  while ((sink = AST_RWLIST_REMOVE_HEAD(&sinks, list))) {
71  ast_mutex_destroy(&sink->lock);
72  ast_free(sink);
73  }
74 }
75 
76 static int syslog_log(struct ast_cdr *cdr)
77 {
78  struct ast_channel *dummy;
79  struct ast_str *str;
80  struct cdr_config *sink;
81 
82  /* Batching saves memory management here. Otherwise, it's the same as doing an
83  allocation and free each time. */
84  if (!(str = ast_str_thread_get(&syslog_buf, 16))) {
85  return -1;
86  }
87 
88  if (!(dummy = ast_dummy_channel_alloc())) {
89  ast_log(AST_LOG_ERROR, "Unable to allocate channel for variable substitution.\n");
90  return -1;
91  }
92 
93  /* We need to dup here since the cdr actually belongs to the other channel,
94  so when we release this channel we don't want the CDR getting cleaned
95  up prematurely. */
96  dummy->cdr = ast_cdr_dup(cdr);
97 
99 
100  AST_LIST_TRAVERSE(&sinks, sink, list) {
101 
102  ast_str_substitute_variables(&str, 0, dummy, sink->format);
103 
104  /* Even though we have a lock on the list, we could be being chased by
105  another thread and this lock ensures that we won't step on anyone's
106  toes. Once each CDR backend gets it's own thread, this lock can be
107  removed. */
108  ast_mutex_lock(&sink->lock);
109 
110  openlog(sink->ident, LOG_CONS, sink->facility);
111  syslog(sink->priority, "%s", ast_str_buffer(str));
112  closelog();
113 
114  ast_mutex_unlock(&sink->lock);
115  }
116 
118 
119  ast_channel_unref(dummy);
120 
121  return 0;
122 }
123 
124 static int load_config(int reload)
125 {
126  struct ast_config *cfg;
127  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
128  int default_facility = LOG_LOCAL4;
129  int default_priority = LOG_INFO;
130  const char *catg = NULL, *tmp;
131 
132  cfg = ast_config_load(CONFIG, config_flags);
135  "Unable to load %s. Not logging custom CSV CDRs to syslog.\n", CONFIG);
136  return -1;
137  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
138  return 0;
139  }
140 
141  if (reload) {
142  free_config();
143  }
144 
145  if (!(ast_strlen_zero(tmp = ast_variable_retrieve(cfg, "general", "facility")))) {
146  int facility = ast_syslog_facility(tmp);
147  if (facility < 0) {
149  "Invalid facility '%s' specified, defaulting to '%s'\n",
150  tmp, ast_syslog_facility_name(default_facility));
151  } else {
152  default_facility = facility;
153  }
154  }
155 
156  if (!(ast_strlen_zero(tmp = ast_variable_retrieve(cfg, "general", "priority")))) {
157  int priority = ast_syslog_priority(tmp);
158  if (priority < 0) {
160  "Invalid priority '%s' specified, defaulting to '%s'\n",
161  tmp, ast_syslog_priority_name(default_priority));
162  } else {
163  default_priority = priority;
164  }
165  }
166 
167  while ((catg = ast_category_browse(cfg, catg))) {
168  struct cdr_config *sink;
169 
170  if (!strcasecmp(catg, "general")) {
171  continue;
172  }
173 
174  if (ast_strlen_zero(tmp = ast_variable_retrieve(cfg, catg, "template"))) {
176  "No 'template' parameter found for '%s'. Skipping.\n", catg);
177  continue;
178  }
179 
180  sink = ast_calloc_with_stringfields(1, struct cdr_config, 1024);
181 
182  if (!sink) {
184  "Unable to allocate memory for configuration settings.\n");
185  free_config();
186  break;
187  }
188 
189  ast_mutex_init(&sink->lock);
190  ast_string_field_set(sink, ident, catg);
191  ast_string_field_set(sink, format, tmp);
192 
193  if (ast_strlen_zero(tmp = ast_variable_retrieve(cfg, catg, "facility"))) {
194  sink->facility = default_facility;
195  } else {
196  int facility = ast_syslog_facility(tmp);
197  if (facility < 0) {
199  "Invalid facility '%s' specified for '%s,' defaulting to '%s'\n",
200  tmp, catg, ast_syslog_facility_name(default_facility));
201  } else {
202  sink->facility = facility;
203  }
204  }
205 
206  if (ast_strlen_zero(tmp = ast_variable_retrieve(cfg, catg, "priority"))) {
207  sink->priority = default_priority;
208  } else {
209  int priority = ast_syslog_priority(tmp);
210  if (priority < 0) {
212  "Invalid priority '%s' specified for '%s,' defaulting to '%s'\n",
213  tmp, catg, ast_syslog_priority_name(default_priority));
214  } else {
215  sink->priority = priority;
216  }
217  }
218 
220  }
221 
222  ast_config_destroy(cfg);
223 
224  return AST_RWLIST_EMPTY(&sinks) ? -1 : 0;
225 }
226 
227 static int unload_module(void)
228 {
229  ast_cdr_unregister(name);
230 
231  if (AST_RWLIST_WRLOCK(&sinks)) {
233  ast_log(AST_LOG_ERROR, "Unable to lock sink list. Unload failed.\n");
234  return -1;
235  }
236 
237  free_config();
239  return 0;
240 }
241 
243 {
244  int res;
245 
246  if (AST_RWLIST_WRLOCK(&sinks)) {
247  ast_log(AST_LOG_ERROR, "Unable to lock sink list. Load failed.\n");
249  }
250 
251  res = load_config(0);
253  if (res) {
255  }
258 }
259 
260 static int reload(void)
261 {
262  int res;
263  if (AST_RWLIST_WRLOCK(&sinks)) {
264  ast_log(AST_LOG_ERROR, "Unable to lock sink list. Load failed.\n");
266  }
267 
268  if ((res = load_config(1))) {
269  free_config();
270  }
271 
273 
275 }
276 
277 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Customizable syslog CDR Backend",
278  .load = load_module,
279  .unload = unload_module,
280  .reload = reload,
281  .load_pri = AST_MODPRI_CDR_DRIVER,
282 );
const char * description
Definition: module.h:234
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Definition: threadstorage.h:81
ast_module_load_result
Definition: module.h:60
Main Channel structure associated with a channel.
Definition: channel.h:742
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
int ast_syslog_priority(const char *priority)
Maps a syslog priority name from a string to a syslog priority constant.
Definition: syslog.c:128
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
Definition: linkedlists.h:332
int priority
Definition: cdr_syslog.c:60
static int load_config(int reload)
Definition: cdr_syslog.c:124
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
static void dummy(char *unused,...)
Definition: chan_unistim.c:188
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_LOG_WARNING
Definition: logger.h:149
struct ast_cdr * ast_cdr_dup(struct ast_cdr *cdr)
Duplicate a record.
Definition: cdr.c:213
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
Definition: pbx.c:4468
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:275
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:235
#define ast_mutex_lock(a)
Definition: lock.h:155
struct ast_cdr * cdr
Definition: channel.h:766
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:374
const char * str
Definition: app_jack.c:144
const char * ast_syslog_priority_name(int priority)
Maps a syslog priority constant to a string.
Definition: syslog.c:141
const ast_string_field ident
Definition: cdr_syslog.c:58
int facility
Definition: cdr_syslog.c:59
static int reload(void)
Definition: cdr_syslog.c:260
static void free_config(void)
Definition: cdr_syslog.c:67
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
#define CONFIG_STATUS_FILEMISSING
Definition: config.h:50
Call Detail Record API.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_LOG_ERROR
Definition: logger.h:160
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
Definition: cdr.c:130
struct cdr_config::@76 list
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static int syslog_log(struct ast_cdr *cdr)
Definition: cdr_syslog.c:76
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:220
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
Syslog support functions for Asterisk logging.
Core PBX routines and definitions.
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:451
Responsible for call detail data.
Definition: cdr.h:82
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
static enum ast_module_load_result load_module(void)
Definition: cdr_syslog.c:242
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_threadstorage syslog_buf
Definition: cdr_syslog.c:50
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
static const char name[]
#define ast_free(a)
Definition: astmm.h:97
#define AST_RWLIST_REMOVE_HEAD
Definition: linkedlists.h:829
Structure used to handle boolean flags.
Definition: utils.h:200
static const char CONFIG[]
Definition: cdr_syslog.c:48
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:726
const ast_string_field format
Definition: cdr_custom.c:65
int ast_syslog_facility(const char *facility)
Maps a syslog facility name from a string to a syslog facility constant.
Definition: syslog.c:87
#define ast_mutex_init(pmutex)
Definition: lock.h:152
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:669
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
#define ast_mutex_destroy(a)
Definition: lock.h:154
struct ast_channel * ast_dummy_channel_alloc(void)
Create a fake channel structure.
Definition: channel.c:1391
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
static int unload_module(void)
Definition: cdr_syslog.c:227
const char * ast_syslog_facility_name(int facility)
Maps a syslog facility constant to a string.
Definition: syslog.c:100
void ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition: cdr.c:165
Structure for mutex and tracking information.
Definition: lock.h:121
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
#define ast_mutex_unlock(a)
Definition: lock.h:156
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
ast_mutex_t lock
Definition: cdr_custom.c:66