Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
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 <[email protected]>
24  *
25  * See also
26  * \arg \ref Config_cdr
27  * \ingroup cdr_drivers
28  */
29 
30 /*! \li \ref cdr_syslog.c uses the configuration file \ref cdr_syslog.conf
31  * \addtogroup configuration_file Configuration Files
32  */
33 
34 /*!
35  * \page cdr_syslog.conf cdr_syslog.conf
36  * \verbinclude cdr_syslog.conf.sample
37  */
38 
39 /*** MODULEINFO
40  <depend>syslog</depend>
41  <defaultenabled>no</defaultenabled>
42  <support_level>deprecated</support_level>
43 ***/
44 
45 #include "asterisk.h"
46 
47 #include "asterisk/module.h"
48 #include "asterisk/lock.h"
49 #include "asterisk/cdr.h"
50 #include "asterisk/pbx.h"
51 
52 #include <syslog.h>
53 
54 #include "asterisk/syslog.h"
55 
56 static const char CONFIG[] = "cdr_syslog.conf";
57 
59 
60 static const char name[] = "cdr-syslog";
61 
66  );
67  int facility;
68  int priority;
71 };
72 
74 
75 static void free_config(void)
76 {
77  struct cdr_syslog_config *sink;
78 
79  while ((sink = AST_RWLIST_REMOVE_HEAD(&sinks, list))) {
80  ast_mutex_destroy(&sink->lock);
82  ast_free(sink);
83  }
84 }
85 
86 static int syslog_log(struct ast_cdr *cdr)
87 {
88  struct ast_channel *dummy;
89  struct ast_str *str;
90  struct cdr_syslog_config *sink;
91 
92  /* Batching saves memory management here. Otherwise, it's the same as doing an
93  allocation and free each time. */
94  if (!(str = ast_str_thread_get(&syslog_buf, 16))) {
95  return -1;
96  }
97 
98  if (!(dummy = ast_dummy_channel_alloc())) {
99  ast_log(AST_LOG_ERROR, "Unable to allocate channel for variable substitution.\n");
100  return -1;
101  }
102 
103  /* We need to dup here since the cdr actually belongs to the other channel,
104  so when we release this channel we don't want the CDR getting cleaned
105  up prematurely. */
106  ast_channel_cdr_set(dummy, ast_cdr_dup(cdr));
107 
109 
110  AST_LIST_TRAVERSE(&sinks, sink, list) {
111 
112  ast_str_substitute_variables(&str, 0, dummy, sink->format);
113 
114  /* Even though we have a lock on the list, we could be being chased by
115  another thread and this lock ensures that we won't step on anyone's
116  toes. Once each CDR backend gets it's own thread, this lock can be
117  removed. */
118  ast_mutex_lock(&sink->lock);
119 
120  openlog(sink->ident, LOG_CONS, sink->facility);
121  syslog(sink->priority, "%s", ast_str_buffer(str));
122  closelog();
123 
124  ast_mutex_unlock(&sink->lock);
125  }
126 
128 
129  ast_channel_unref(dummy);
130 
131  return 0;
132 }
133 
134 static int load_config(int reload)
135 {
136  struct ast_config *cfg;
137  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
138  int default_facility = LOG_LOCAL4;
139  int default_priority = LOG_INFO;
140  const char *catg = NULL, *tmp;
141 
142  cfg = ast_config_load(CONFIG, config_flags);
145  "Unable to load %s. Not logging custom CSV CDRs to syslog.\n", CONFIG);
146  return -1;
147  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
148  return 0;
149  }
150 
151  if (reload) {
152  free_config();
153  }
154 
155  if (!(ast_strlen_zero(tmp = ast_variable_retrieve(cfg, "general", "facility")))) {
156  int facility = ast_syslog_facility(tmp);
157  if (facility < 0) {
159  "Invalid facility '%s' specified, defaulting to '%s'\n",
160  tmp, ast_syslog_facility_name(default_facility));
161  } else {
162  default_facility = facility;
163  }
164  }
165 
166  if (!(ast_strlen_zero(tmp = ast_variable_retrieve(cfg, "general", "priority")))) {
167  int priority = ast_syslog_priority(tmp);
168  if (priority < 0) {
170  "Invalid priority '%s' specified, defaulting to '%s'\n",
171  tmp, ast_syslog_priority_name(default_priority));
172  } else {
173  default_priority = priority;
174  }
175  }
176 
177  while ((catg = ast_category_browse(cfg, catg))) {
178  struct cdr_syslog_config *sink;
179 
180  if (!strcasecmp(catg, "general")) {
181  continue;
182  }
183 
184  if (ast_strlen_zero(tmp = ast_variable_retrieve(cfg, catg, "template"))) {
186  "No 'template' parameter found for '%s'. Skipping.\n", catg);
187  continue;
188  }
189 
190  sink = ast_calloc_with_stringfields(1, struct cdr_syslog_config, 1024);
191 
192  if (!sink) {
194  "Unable to allocate memory for configuration settings.\n");
195  free_config();
196  break;
197  }
198 
199  ast_mutex_init(&sink->lock);
200  ast_string_field_set(sink, ident, catg);
201  ast_string_field_set(sink, format, tmp);
202 
203  if (ast_strlen_zero(tmp = ast_variable_retrieve(cfg, catg, "facility"))) {
204  sink->facility = default_facility;
205  } else {
206  int facility = ast_syslog_facility(tmp);
207  if (facility < 0) {
209  "Invalid facility '%s' specified for '%s,' defaulting to '%s'\n",
210  tmp, catg, ast_syslog_facility_name(default_facility));
211  } else {
212  sink->facility = facility;
213  }
214  }
215 
216  if (ast_strlen_zero(tmp = ast_variable_retrieve(cfg, catg, "priority"))) {
217  sink->priority = default_priority;
218  } else {
219  int priority = ast_syslog_priority(tmp);
220  if (priority < 0) {
222  "Invalid priority '%s' specified for '%s,' defaulting to '%s'\n",
223  tmp, catg, ast_syslog_priority_name(default_priority));
224  } else {
225  sink->priority = priority;
226  }
227  }
228 
230  }
231 
232  ast_config_destroy(cfg);
233 
234  return AST_RWLIST_EMPTY(&sinks) ? -1 : 0;
235 }
236 
237 static int unload_module(void)
238 {
239  if (ast_cdr_unregister(name)) {
240  return -1;
241  }
242 
243  if (AST_RWLIST_WRLOCK(&sinks)) {
245  ast_log(AST_LOG_ERROR, "Unable to lock sink list. Unload failed.\n");
246  return -1;
247  }
248 
249  free_config();
251  return 0;
252 }
253 
255 {
256  int res;
257 
258  if (AST_RWLIST_WRLOCK(&sinks)) {
259  ast_log(AST_LOG_ERROR, "Unable to lock sink list. Load failed.\n");
261  }
262 
263  res = load_config(0);
265  if (res) {
267  }
270 }
271 
272 static int reload(void)
273 {
274  int res;
275  if (AST_RWLIST_WRLOCK(&sinks)) {
276  ast_log(AST_LOG_ERROR, "Unable to lock sink list. Load failed.\n");
278  }
279 
280  if ((res = load_config(1))) {
281  free_config();
282  }
283 
285 
287 }
288 
289 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Customizable syslog CDR Backend",
290  .support_level = AST_MODULE_SUPPORT_CORE,
291  .load = load_module,
292  .unload = unload_module,
293  .reload = reload,
294  .load_pri = AST_MODPRI_CDR_DRIVER,
295  .requires = "cdr",
296 );
const char * description
Definition: module.h:352
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Definition: threadstorage.h:84
ast_module_load_result
Definition: module.h:68
Main Channel structure associated with a channel.
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:126
int ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition: cdr.c:2988
#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
static int load_config(int reload)
Definition: cdr_syslog.c:134
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#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:714
static void dummy(char *unused,...)
Definition: chan_unistim.c:220
#define CONFIG_STATUS_FILEINVALID
static int tmp()
Definition: bt_open.c:389
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_LOG_WARNING
Definition: logger.h:279
struct ast_cdr * ast_cdr_dup(struct ast_cdr *cdr)
Duplicate a public CDR.
Definition: cdr.c:2998
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:426
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:337
#define ast_mutex_lock(a)
Definition: lock.h:187
const char * str
Definition: app_jack.c:147
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
const char * ast_syslog_priority_name(int priority)
Maps a syslog priority constant to a string.
Definition: syslog.c:139
#define NULL
Definition: resample.c:96
static int reload(void)
Definition: cdr_syslog.c:272
static void free_config(void)
Definition: cdr_syslog.c:75
#define ast_strlen_zero(foo)
Definition: strings.h:52
static const char name[]
Definition: cdr_syslog.c:60
Call Detail Record API.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_log
Definition: astobj2.c:42
void ast_channel_cdr_set(struct ast_channel *chan, struct ast_cdr *value)
#define ast_config_load(filename, flags)
Load a config file.
#define AST_LOG_ERROR
Definition: logger.h:290
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
Definition: cdr.c:2943
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1283
static int syslog_log(struct ast_cdr *cdr)
Definition: cdr_syslog.c:86
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:299
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
struct cdr_syslog_config::@102 list
Syslog support functions for Asterisk logging.
Core PBX routines and definitions.
#define CONFIG_STATUS_FILEUNCHANGED
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:451
Responsible for call detail data.
Definition: cdr.h:276
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static enum ast_module_load_result load_module(void)
Definition: cdr_syslog.c:254
static struct ast_threadstorage syslog_buf
Definition: cdr_syslog.c:58
#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
#define ast_free(a)
Definition: astmm.h:182
#define AST_RWLIST_REMOVE_HEAD
Definition: linkedlists.h:843
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
Structure used to handle boolean flags.
Definition: utils.h:199
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
static const char CONFIG[]
Definition: cdr_syslog.c:56
#define CONFIG_STATUS_FILEMISSING
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740
ast_mutex_t lock
Definition: cdr_syslog.c:69
int ast_syslog_facility(const char *facility)
Maps a syslog facility name from a string to a syslog facility constant.
Definition: syslog.c:85
const ast_string_field ident
Definition: cdr_syslog.c:66
#define ast_mutex_init(pmutex)
Definition: lock.h:184
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:861
#define ast_mutex_destroy(a)
Definition: lock.h:186
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
const ast_string_field format
Definition: cdr_syslog.c:66
Asterisk module definitions.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
static int unload_module(void)
Definition: cdr_syslog.c:237
const char * ast_syslog_facility_name(int facility)
Maps a syslog facility constant to a string.
Definition: syslog.c:98
Structure for mutex and tracking information.
Definition: lock.h:135
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514