Coverage Report

Created: 2025-08-28 06:16

/src/opensips/dprint.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * debug print
3
 *
4
 * Copyright (C) 2001-2003 FhG Fokus
5
 *
6
 * This file is part of opensips, a free SIP server.
7
 *
8
 * opensips is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version
12
 *
13
 * opensips is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
21
 */
22
23
/*!
24
 * \file
25
 * \brief OpenSIPS Debug console print functions
26
 */
27
28
#include "dprint.h"
29
#include "log_interface.h"
30
#include "globals.h"
31
#include "pt.h"
32
33
#include <stdarg.h>
34
#include <stdio.h>
35
#include <strings.h>
36
37
#if !defined(HOST_NAME_MAX)
38
#define HOST_NAME_MAX 255
39
#endif
40
41
/* used internally by the log interface */
42
typedef void (*log_print_pre_fmt_f)(log_print_f gen_print_func, int log_level,
43
  int facility, const char *module, const char *func,
44
  char *stderr_plain_fmt, char *syslog_plain_fmt, char *format, va_list ap);
45
46
struct log_consumer_t {
47
  str name;
48
  log_print_f gen_print_func;
49
  log_print_pre_fmt_f pre_fmt_print_func;
50
  int level_filter;
51
  int muted;
52
};
53
54
static int log_level_holder = L_NOTICE;
55
enum log_format stderr_log_format = LOG_FORMAT_PLAIN;
56
enum log_format syslog_log_format = LOG_FORMAT_PLAIN;
57
58
/* shared holder with the globally set log_level */
59
static int *log_level_global = NULL;
60
61
/* current logging level for this process */
62
int *log_level = &log_level_holder;
63
char *log_prefix = "";
64
65
/* used when resetting the logging level of this process */
66
static int *default_log_level;
67
68
static char *log_json_buf = NULL;
69
int log_json_buf_size = 6144;
70
static char *log_msg_buf = NULL;
71
int log_msg_buf_size = 4096;
72
73
str log_cee_hostname;
74
75
static void stderr_dprint(int log_level, int facility, const char *module, const char *func,
76
  char *format, va_list ap);
77
static void syslog_dprint(int log_level, int facility, const char *module, const char *func,
78
  char *format, va_list ap);
79
80
static void stderr_pre_fmt_func(log_print_f gen_print_func, int log_level,
81
  int facility, const char *module, const char *func,
82
  char *stderr_plain_fmt, char *syslog_plain_fmt, char *format, va_list ap);
83
static void syslog_pre_fmt_func(log_print_f gen_print_func, int log_level,
84
  int facility, const char *module, const char *func,
85
  char *stderr_plain_fmt, char *syslog_plain_fmt, char *format, va_list ap);
86
87
/* static consumer table to be used until a shm one is alloc'ed;
88
 * only stderror is enabled initially */
89
static struct log_consumer_t default_log_consumers[2] ={
90
  {str_init(STDERR_CONSUMER_NAME), stderr_dprint, stderr_pre_fmt_func, 0, 0},
91
  {str_init(SYSLOG_CONSUMER_NAME), syslog_dprint, syslog_pre_fmt_func, 0, 1}
92
};
93
94
struct log_consumer_t *log_consumers = default_log_consumers;
95
int log_consumers_no = 2;
96
97
int log_event_enabled = 0;
98
int log_event_level_filter = 0;
99
static str evi_log_name = str_init("E_CORE_LOG");
100
static event_id_t evi_log_id;
101
102
static char* str_fac[]={"LOG_AUTH","LOG_CRON","LOG_DAEMON",
103
          "LOG_KERN","LOG_LOCAL0","LOG_LOCAL1",
104
          "LOG_LOCAL2","LOG_LOCAL3","LOG_LOCAL4","LOG_LOCAL5",
105
          "LOG_LOCAL6","LOG_LOCAL7","LOG_LPR","LOG_MAIL",
106
          "LOG_NEWS","LOG_USER","LOG_UUCP",
107
#ifndef __OS_solaris
108
          "LOG_AUTHPRIV","LOG_FTP","LOG_SYSLOG",
109
#endif
110
          0};
111
static int int_fac[]={LOG_AUTH ,  LOG_CRON , LOG_DAEMON ,
112
          LOG_KERN , LOG_LOCAL0 , LOG_LOCAL1 ,
113
          LOG_LOCAL2 , LOG_LOCAL3 , LOG_LOCAL4 , LOG_LOCAL5 ,
114
          LOG_LOCAL6 , LOG_LOCAL7 , LOG_LPR , LOG_MAIL ,
115
          LOG_NEWS , LOG_USER , LOG_UUCP
116
#ifndef __OS_solaris
117
          ,LOG_AUTHPRIV,LOG_FTP,LOG_SYSLOG
118
#endif
119
          };
120
121
char ctime_buf[256];
122
123
int str2facility(char *s)
124
0
{
125
0
  int i;
126
127
0
  for( i=0; str_fac[i] ; i++) {
128
0
    if (!strcasecmp(s,str_fac[i]))
129
0
      return int_fac[i];
130
0
  }
131
0
  return -1;
132
0
}
133
134
135
int dp_my_pid(void)
136
0
{
137
0
  return my_pid();
138
0
}
139
140
int parse_log_format(str *format)
141
0
{
142
0
  if (str_match(format, (&str_init(LOG_PLAIN_NAME))))
143
0
    return LOG_FORMAT_PLAIN;
144
0
  else if (str_match(format, (&str_init(LOG_JSON_NAME))))
145
0
    return LOG_FORMAT_JSON;
146
0
  else if (str_match(format, (&str_init(LOG_JSON_CEE_NAME))))
147
0
    return LOG_FORMAT_JSON_CEE;
148
0
  else
149
0
    return -1;
150
0
}
151
152
void stderr_dprint_tmp(char *format, ...)
153
0
{
154
0
  va_list ap;
155
156
0
  va_start(ap, format);
157
0
  vfprintf(stderr,format,ap);
158
0
  fflush(stderr);
159
0
  va_end(ap);
160
0
}
161
162
int init_log_cee_hostname(void)
163
0
{
164
0
  struct addrinfo hints, *info = NULL;
165
0
  char hostname[HOST_NAME_MAX+1];
166
0
  int rc;
167
0
  str cname;
168
169
0
  if (log_cee_hostname.s)
170
0
    return 0;
171
172
0
  gethostname (hostname, HOST_NAME_MAX);
173
174
0
  memset(&hints, 0, sizeof hints);
175
0
  hints.ai_family = AF_UNSPEC;
176
0
  hints.ai_socktype = SOCK_STREAM;
177
0
  hints.ai_flags = AI_CANONNAME;
178
179
0
  rc = getaddrinfo(hostname, 0, &hints, &info);
180
0
  if (!rc && info) {
181
0
    init_str(&cname, info->ai_canonname);
182
0
    if (pkg_str_dup(&log_cee_hostname, &cname) < 0) {
183
0
      LM_ERR("no more pkg memory\n");
184
0
      freeaddrinfo(info);
185
0
      return -1;
186
0
    }
187
0
  }
188
189
0
  if (info)
190
0
    freeaddrinfo(info);
191
192
0
  return 0;
193
0
}
194
195
#define append_string(_d,_s,_len) \
196
0
  do{\
197
0
    memcpy((_d),(_s),(_len));\
198
0
    (_d) += (_len);\
199
0
    len += (_len);\
200
0
  }while(0)
201
202
#define append_string_st(_d,_s) \
203
0
  do{\
204
0
    memcpy((_d),(_s),sizeof(_s) - 1);\
205
0
    (_d) += sizeof(_s) - 1;\
206
0
    len += sizeof(_s) - 1;\
207
0
  }while(0)
208
209
0
#define S_LEN(_s) (sizeof(_s) - 1)
210
211
#define DP_JSON_TIME_KEY      "{\"time\": \""
212
#define DP_JSON_PID_KEY       "\", \"pid\": "
213
#define DP_JSON_LEVEL_KEY     ", \"level\": \""
214
#define DP_JSON_MODULE_KEY    "\", \"module\": \""
215
#define DP_JSON_FUNC_KEY      "\", \"function\": \""
216
#define DP_JSON_PREFIX_KEY    "\", \"prefix\": \""
217
#define DP_JSON_MSG_KEY       "\", \"message\": \""
218
219
#define DP_JSON_CEE_AT_PREFIX    "@cee: "
220
#define DP_JSON_CEE_TIME_KEY     "{\"time\": \""
221
#define DP_JSON_CEE_PID_KEY      "\", \"proc\": {\"id\": \""
222
#define DP_JSON_CEE_LEVEL_KEY    "\"}, \"pri\": \""
223
#define DP_JSON_CEE_MODULE_KEY   "\", \"subsys\": \""
224
#define DP_JSON_CEE_FUNC_KEY     "\", \"native\": {\"function\": \""
225
#define DP_JSON_CEE_PREFIX_KEY   "\", \"log_prefix\": \""
226
#define DP_JSON_CEE_PREFIX_O_KEY "\", \"native\": {\"log_prefix\": \""
227
#define DP_JSON_CEE_MSG_B_KEY    "\"}, \"msg\": \""
228
#define DP_JSON_CEE_MSG_KEY      "\", \"msg\": \""
229
#define DP_JSON_CEE_PNAME_KEY    "\", \"pname\": \""
230
#define DP_JSON_CEE_PNAME_VAL    "opensips"
231
#define DP_JSON_CEE_HOST_KEY     "\", \"hostname\": \""
232
233
#define DP_JSON_MSG_END       "\"}"
234
235
static int log_escape_json_buf(char *src, int src_len, char *dst, int dst_max_len)
236
0
{
237
0
  int i, j = 0;
238
0
  int rlen = 0;
239
240
  /* calculate the required length in the dst buffer */
241
0
  for (i=0; i<src_len; i++) {
242
0
    rlen++;
243
244
0
    switch (src[i]) {
245
0
    case '\\':
246
0
    case '\"':
247
0
    case '\b':
248
0
    case '\f':
249
0
    case '\n':
250
0
    case '\r':
251
0
    case '\t':
252
0
      rlen++;  /* +1 for the backslash */
253
0
        break;
254
0
    default:
255
0
      if (src[i] < 32)
256
0
        rlen += 6;  /* +6 for \uXXXX */
257
0
    }
258
0
  }
259
260
0
  if (rlen>dst_max_len) {
261
0
    stderr_dprint_tmp_err("buffer too small! needed: %d\n", rlen);
262
0
    return -1;
263
0
  } else if (rlen == src_len) {
264
    /* nothing needs to be escaped */
265
0
    memcpy(dst, src, src_len);
266
0
    return src_len;
267
0
  }
268
269
0
  for (i=0; i<src_len; i++) {
270
0
    if (src[i] > 31 && src[i] != '\\' && src[i] != '\"') {
271
0
      dst[j++] = src[i];
272
0
    } else {
273
0
      dst[j++] = '\\';
274
275
0
      switch (src[i]) {
276
0
      case '\\':
277
0
        dst[j++] = '\\';
278
0
        break;
279
0
      case '\"':
280
0
        dst[j++] = '\"';
281
0
        break;
282
0
      case '\b':
283
0
        dst[j++] = 'b';
284
0
        break;
285
0
      case '\f':
286
0
        dst[j++] = 'f';
287
0
        break;
288
0
      case '\n':
289
0
        dst[j++] = 'n';
290
0
        break;
291
0
      case '\r':
292
0
        dst[j++] = 'r';
293
0
        break;
294
0
      case '\t':
295
0
        dst[j++] = 't';
296
0
        break;
297
0
      default:
298
        /* escape and print as unicode codepoint */
299
0
        sprintf(dst+j, "u%04x", src[i]);
300
0
        j += 5;
301
0
      }
302
0
    }
303
0
  }
304
305
0
  return j;
306
0
}
307
308
enum log_json_format {
309
  LOG_JSON_SCHEMA_BASIC,
310
  LOG_JSON_SCHEMA_CEE,
311
  LOG_JSON_SCHEMA_CEE_PREFIX  /* for syslog, JSON prefixed with "@cee: " */
312
};
313
314
static int log_print_json(str *buf, enum log_json_format json_fmt, char *time,
315
  int pid, char *prefix, const char *level, const char *module, const char *func,
316
  char *format, va_list ap)
317
0
{
318
0
  char *p, *tmp;
319
0
  int len = 0, rlen;
320
0
  int l;
321
322
0
  if (json_fmt > LOG_JSON_SCHEMA_BASIC) {
323
0
    rlen = S_LEN(DP_JSON_CEE_PNAME_KEY) + (log_name ? strlen(log_name) :
324
0
      S_LEN(DP_JSON_CEE_PNAME_VAL)) + S_LEN(DP_JSON_CEE_HOST_KEY) +
325
0
      log_cee_hostname.len + S_LEN(DP_JSON_MSG_END) + 1;
326
327
0
    if (json_fmt == LOG_JSON_SCHEMA_CEE_PREFIX)
328
0
      len = S_LEN(DP_JSON_CEE_AT_PREFIX);
329
330
0
    len += S_LEN(DP_JSON_CEE_TIME_KEY) + strlen(time) +
331
0
      S_LEN(DP_JSON_CEE_PID_KEY) + INT2STR_MAX_LEN +
332
0
      S_LEN(DP_JSON_CEE_LEVEL_KEY) + strlen(level) +
333
0
      (module && func ?
334
0
      S_LEN(DP_JSON_CEE_MODULE_KEY) + strlen(module) +
335
0
      S_LEN(DP_JSON_CEE_FUNC_KEY) + strlen(func) : 0) +
336
0
      S_LEN(DP_JSON_CEE_PREFIX_O_KEY) + strlen(prefix) +
337
0
      S_LEN(DP_JSON_MSG_KEY) + rlen;
338
0
  } else {
339
0
    rlen = S_LEN(DP_JSON_MSG_END) + 1;
340
341
0
    len = S_LEN(DP_JSON_TIME_KEY) + strlen(time) + S_LEN(DP_JSON_PID_KEY) +
342
0
      INT2STR_MAX_LEN + S_LEN(DP_JSON_LEVEL_KEY) + strlen(level) +
343
0
      (module && func ? S_LEN(DP_JSON_MODULE_KEY) + strlen(module) +
344
0
      S_LEN(DP_JSON_FUNC_KEY) + strlen(func) : 0) +
345
0
      S_LEN(DP_JSON_PREFIX_KEY) + strlen(prefix) +
346
0
      S_LEN(DP_JSON_CEE_MSG_B_KEY) + rlen;
347
0
  }
348
349
0
  if (len >= buf->len) {
350
0
    stderr_dprint_tmp_err("buffer too small! needed: %d\n", len);
351
0
    return -1;
352
0
  }
353
354
0
  len = 0;
355
0
  p = buf->s;
356
357
0
  if (json_fmt > LOG_JSON_SCHEMA_BASIC) {
358
0
    if (json_fmt == LOG_JSON_SCHEMA_CEE_PREFIX)
359
0
      append_string_st(p, DP_JSON_CEE_AT_PREFIX);
360
361
0
    append_string_st(p, DP_JSON_CEE_TIME_KEY);
362
0
    append_string(p, time, strlen(time));
363
364
0
    append_string_st(p, DP_JSON_CEE_PID_KEY);
365
0
    tmp = int2str(pid, &l);
366
0
    append_string(p, tmp, l);
367
368
0
    append_string_st(p, DP_JSON_CEE_LEVEL_KEY);
369
0
    append_string(p, level, strlen(level));
370
371
0
    if (module && func) {
372
0
      append_string_st(p, DP_JSON_CEE_MODULE_KEY);
373
0
      append_string(p, module, strlen(module));
374
375
0
      append_string_st(p, DP_JSON_CEE_FUNC_KEY);
376
0
      append_string(p, func, strlen(func));
377
0
    }
378
379
0
    if (strlen(prefix) != 0) {
380
0
      if (module && func)
381
0
        append_string_st(p, DP_JSON_CEE_PREFIX_KEY);
382
0
      else
383
0
        append_string_st(p, DP_JSON_CEE_PREFIX_O_KEY);
384
0
      append_string(p, prefix, strlen(prefix)-1/*skip the ':'*/);
385
0
    }
386
387
0
    if ((module && func) || strlen(prefix) != 0)
388
0
      append_string_st(p, DP_JSON_CEE_MSG_B_KEY);
389
0
    else
390
0
      append_string_st(p, DP_JSON_CEE_MSG_KEY);
391
0
  } else {
392
0
    append_string_st(p, DP_JSON_TIME_KEY);
393
0
    append_string(p, time, strlen(time));
394
395
0
    append_string_st(p, DP_JSON_PID_KEY);
396
0
    tmp = int2str(pid, &l);
397
0
    append_string(p, tmp, l);
398
399
0
    append_string_st(p, DP_JSON_LEVEL_KEY);
400
0
    append_string(p, level, strlen(level));
401
402
0
    if (module && func) {
403
0
      append_string_st(p, DP_JSON_MODULE_KEY);
404
0
      append_string(p, module, strlen(module));
405
406
0
      append_string_st(p, DP_JSON_FUNC_KEY);
407
0
      append_string(p, func, strlen(func));
408
0
    }
409
410
0
    if (strlen(prefix) != 0) {
411
0
      append_string_st(p, DP_JSON_PREFIX_KEY);
412
0
      append_string(p, prefix, strlen(prefix)-1/*skip the ':'*/);
413
0
    }
414
415
0
    append_string_st(p, DP_JSON_MSG_KEY);
416
0
  }
417
418
0
  l = vsnprintf(log_msg_buf, log_msg_buf_size, format, ap);
419
0
  if (l < 0) {
420
0
    stderr_dprint_tmp_err("vsnprintf() failed!\n");
421
0
    return -1;
422
0
  }
423
0
  if (l >= log_msg_buf_size) {
424
0
    stderr_dprint_tmp_err("warning: buffer too small, log message truncated\n");
425
0
    l = log_msg_buf_size;
426
0
  }
427
428
0
  l = log_escape_json_buf(log_msg_buf, l, p,
429
0
    buf->len - len - rlen - 1);
430
0
  if (l < 0) {
431
0
    stderr_dprint_tmp_err("failed to escape log message!\n");
432
0
    return -1;
433
0
  }
434
435
0
  p += l;
436
0
  len += l;
437
438
0
  if (json_fmt == LOG_JSON_SCHEMA_BASIC) {
439
0
    append_string_st(p, DP_JSON_MSG_END);
440
0
  } else {
441
0
    append_string_st(p, DP_JSON_CEE_PNAME_KEY);
442
0
    if (log_name)
443
0
      append_string(p, log_name, strlen(log_name));
444
0
    else
445
0
      append_string_st(p, DP_JSON_CEE_PNAME_VAL);
446
447
0
    append_string_st(p, DP_JSON_CEE_HOST_KEY);
448
0
    append_string(p, log_cee_hostname.s, log_cee_hostname.len);
449
450
0
    append_string_st(p, DP_JSON_MSG_END);
451
0
  }
452
453
0
  *p = '\0';
454
455
0
  return len;
456
0
}
457
458
static void stderr_dprint(int log_level, int facility, const char *module, const char *func,
459
  char *format, va_list ap)
460
0
{
461
0
  char *time;
462
0
  int pid;
463
0
  char *prefix;
464
0
  int len;
465
0
  str buf = {log_json_buf, log_json_buf_size};
466
467
0
  if (stderr_log_format != LOG_FORMAT_PLAIN) {
468
0
    time = va_arg(ap, char *);
469
0
    pid = va_arg(ap, int);
470
0
    prefix = va_arg(ap, char *);
471
0
    if (module && func)
472
0
      va_arg(ap, char *);
473
474
0
    if ((len = log_print_json(&buf, stderr_log_format==LOG_FORMAT_JSON_CEE ?
475
0
      LOG_JSON_SCHEMA_CEE : LOG_JSON_SCHEMA_BASIC,
476
0
      time, pid, prefix, dp_log_level_str(log_level), module, func,
477
0
      format, ap)) < 0) {
478
0
      stderr_dprint_tmp_err("failed to print JSON log!\n");
479
0
      return;
480
0
    }
481
482
0
    fprintf(stderr, "%.*s\n", len, log_json_buf);
483
0
    fflush(stderr);
484
0
  } else {
485
0
    vfprintf(stderr,format,ap);
486
0
    fflush(stderr);
487
0
  }
488
0
}
489
490
static void syslog_dprint(int log_level, int facility, const char *module, const char *func,
491
  char *format, va_list ap)
492
0
{
493
0
  int level;
494
0
  char *time;
495
0
  int pid;
496
0
  char *prefix;
497
0
  int len;
498
0
  str buf = {log_json_buf, log_json_buf_size};
499
500
0
  switch (log_level) {
501
0
  case L_ALERT:
502
0
    level = LOG_ALERT;
503
0
    break;
504
0
  case L_CRIT:
505
0
    level = LOG_CRIT;
506
0
    break;
507
0
  case L_ERR:
508
0
    level = LOG_ERR;
509
0
    break;
510
0
  case L_WARN:
511
0
    level = LOG_WARNING;
512
0
    break;
513
0
  case L_NOTICE:
514
0
    level = LOG_NOTICE;
515
0
    break;
516
0
  case L_INFO:
517
0
    level = LOG_INFO;
518
0
    break;
519
0
  case L_DBG:
520
0
  default:
521
0
    level = LOG_DEBUG;
522
0
  }
523
524
0
  if (syslog_log_format != LOG_FORMAT_PLAIN) {
525
0
    time = va_arg(ap, char *);
526
0
    pid = va_arg(ap, int);
527
0
    prefix = va_arg(ap, char *);
528
0
    if (module && func)
529
0
      va_arg(ap, char *);
530
531
0
    if ((len = log_print_json(&buf, syslog_log_format==LOG_FORMAT_JSON_CEE ?
532
0
      LOG_JSON_SCHEMA_CEE_PREFIX : LOG_JSON_SCHEMA_BASIC,
533
0
      time, pid, prefix, dp_log_level_str(log_level), module, func,
534
0
      format, ap)) < 0) {
535
0
      stderr_dprint_tmp_err("failed to print JSON log!\n");
536
0
      return;
537
0
    }
538
539
0
    syslog(level|facility, "%.*s\n", len, log_json_buf);
540
0
  } else {
541
    /* skip the time and pid arguments from va_list */
542
0
    va_arg(ap, char *);
543
0
      va_arg(ap, int);
544
545
0
    vsyslog(level|facility, format, ap);
546
0
  }
547
0
}
548
549
static str evi_time_str = str_init("time");
550
static str evi_pid_str = str_init("pid");
551
static str evi_level_str = str_init("level");
552
static str evi_module_str = str_init("module");
553
static str evi_func_str = str_init("function");
554
static str evi_prefix_str = str_init("prefix");
555
static str evi_msg_str = str_init("message");
556
557
static void event_dprint(int level, int facility, const char *module, const char *func,
558
  char *format, va_list ap)
559
0
{
560
0
  evi_params_p list = NULL;
561
0
  str s;
562
0
  int n;
563
0
  int suppressed;
564
565
0
  suppressed = pt[process_no].suppress_log_event;
566
567
0
  if (suppressed)
568
0
    return;
569
570
0
  pt[process_no].suppress_log_event = 1;
571
572
0
  if (!evi_probe_event(evi_log_id)) {
573
0
    pt[process_no].suppress_log_event = suppressed;
574
0
    return;
575
0
  }
576
577
0
  if (!(list = evi_get_params())) {
578
0
    pt[process_no].suppress_log_event = suppressed;
579
0
    return;
580
0
  }
581
582
0
  init_str(&s, dp_time());
583
0
  if (evi_param_add_str(list, &evi_time_str, &s)) {
584
0
    LM_ERR("unable to add event parameter\n");
585
0
    goto end_free;
586
0
  }
587
0
  n = dp_my_pid();
588
0
  if (evi_param_add_int(list, &evi_pid_str, &n)) {
589
0
    LM_ERR("unable to add event parameter\n");
590
0
    goto end_free;
591
0
  }
592
0
  init_str(&s, dp_log_level_str(level));
593
0
  if (evi_param_add_str(list, &evi_level_str, &s)) {
594
0
    LM_ERR("unable to add event parameter\n");
595
0
    goto end_free;
596
0
  }
597
598
0
  if (module && func) {
599
0
    init_str(&s, module);
600
0
    if (evi_param_add_str(list, &evi_module_str, &s)) {
601
0
      LM_ERR("unable to add event parameter\n");
602
0
      goto end_free;
603
0
    }
604
0
    init_str(&s, func);
605
0
    if (evi_param_add_str(list, &evi_func_str, &s)) {
606
0
      LM_ERR("unable to add event parameter\n");
607
0
      goto end_free;
608
0
    }
609
0
  }
610
611
0
  init_str(&s, log_prefix);
612
0
  if (s.len) {
613
0
    if (evi_param_add_str(list, &evi_prefix_str, &s)) {
614
0
      LM_ERR("unable to add event parameter\n");
615
0
      goto end_free;
616
0
    }
617
0
  }
618
619
0
  s.len = vsnprintf(log_msg_buf, log_msg_buf_size, format, ap);
620
0
  if (s.len < 0) {
621
0
    LM_ERR("vsnprintf() failed!\n");
622
0
    goto end_free;
623
0
  }
624
0
  if (s.len>=log_msg_buf_size) {
625
0
    LM_WARN("log message truncated\n");
626
0
    s.len = log_msg_buf_size;
627
0
  }
628
629
  /* try to strip \n from the end of the "message" param */
630
0
  if (log_msg_buf[s.len-1] == '\n') {
631
0
    log_msg_buf[s.len-1] = '\0';
632
0
    s.len--;
633
0
  }
634
635
0
  s.s = log_msg_buf;
636
0
  if (evi_param_add_str(list, &evi_msg_str, &s)) {
637
0
    LM_ERR("unable to add event parameter\n");
638
0
    goto end_free;
639
0
  }
640
641
0
  if (evi_raise_event(evi_log_id, list)) {
642
0
    LM_ERR("unable to raise '%.*s' event\n",
643
0
      evi_log_name.len, evi_log_name.s);
644
0
  }
645
646
0
  pt[process_no].suppress_log_event = suppressed;
647
648
0
  return;
649
0
end_free:
650
0
  evi_free_params(list);
651
0
  pt[process_no].suppress_log_event = suppressed;
652
0
}
653
654
/* generic consumer that registers to the log interface */
655
static void gen_consumer_pre_fmt_func(log_print_f gen_print_func, int log_level,
656
  int facility, const char *module, const char *func,
657
  char *stderr_plain_fmt, char *syslog_plain_fmt, char *format, va_list ap)
658
0
{
659
  /* skip the time, pid, prefix and function arguments from va_list */
660
0
  va_arg(ap, char *);
661
0
    va_arg(ap, int);
662
0
    va_arg(ap, char *);
663
0
    if (module && func)
664
0
    va_arg(ap, char *);
665
666
0
  gen_print_func(log_level, facility, module, func, format, ap);
667
0
}
668
669
static void stderr_pre_fmt_func(log_print_f gen_print_func, int log_level,
670
  int facility, const char *module, const char *func,
671
  char *stderr_plain_fmt, char *syslog_plain_fmt, char *format, va_list ap)
672
0
{
673
0
  char *fmt = stderr_log_format == LOG_FORMAT_PLAIN ? stderr_plain_fmt : format;
674
675
0
  gen_print_func(log_level, facility, module, func, fmt, ap);
676
0
}
677
678
static void syslog_pre_fmt_func(log_print_f gen_print_func, int log_level,
679
  int facility, const char *module, const char *func,
680
  char *stderr_plain_fmt, char *syslog_plain_fmt, char *format, va_list ap)
681
0
{
682
0
  char *fmt = syslog_log_format == LOG_FORMAT_PLAIN ? syslog_plain_fmt : format;
683
684
0
  gen_print_func(log_level, facility, module, func, fmt, ap);
685
0
}
686
687
void dprint(int log_level, int facility, const char *module, const char *func,
688
  char *stderr_fmt, char *syslog_fmt, char *format, ...)
689
0
{
690
0
  va_list ap, ap_copy;
691
0
  int i;
692
693
0
  va_start(ap, format);
694
695
0
  for (i=0; i<log_consumers_no; i++)
696
0
    if (!log_consumers[i].muted && (!log_consumers[i].level_filter ||
697
0
      log_consumers[i].level_filter >= log_level)) {
698
0
      va_copy(ap_copy, ap);
699
0
      log_consumers[i].pre_fmt_print_func(log_consumers[i].gen_print_func,
700
0
        log_level, facility, module, func, stderr_fmt, syslog_fmt,
701
0
        format, ap_copy);
702
0
      va_end(ap_copy);
703
0
    }
704
705
0
  va_end(ap);
706
0
}
707
708
int register_log_consumer(char *name, log_print_f print_func,
709
  int level_filter, int muted)
710
0
{
711
0
  if (log_consumers_no == MAX_LOG_CONS_NO) {
712
0
    LM_ERR("Maximum number of logging consumers already registered\n");
713
0
    return -1;
714
0
  }
715
716
0
  init_str(&log_consumers[log_consumers_no].name, name);
717
0
  log_consumers[log_consumers_no].gen_print_func = print_func;
718
0
  log_consumers[log_consumers_no].pre_fmt_print_func = gen_consumer_pre_fmt_func;
719
0
  log_consumers[log_consumers_no].level_filter = level_filter;
720
0
  log_consumers[log_consumers_no].muted = muted;
721
722
0
  log_consumers_no++;
723
724
0
  return 0;
725
0
}
726
727
int init_log_json_buf(int realloc_buf)
728
0
{
729
0
  if (realloc_buf && log_json_buf) {
730
0
    log_json_buf = pkg_realloc(log_json_buf, log_json_buf_size+1);
731
0
    if (!log_json_buf) {
732
0
      LM_ERR("no pkg memory left\n");
733
0
      return -1;
734
0
    }
735
0
  } else if (!log_json_buf) {
736
0
    log_json_buf = pkg_malloc(log_json_buf_size+1);
737
0
    if (!log_json_buf) {
738
0
      LM_ERR("no pkg memory left\n");
739
0
      return -1;
740
0
    }
741
0
  }
742
743
0
  return 0;
744
0
}
745
746
int init_log_msg_buf(int realloc_buf)
747
0
{
748
0
  if (realloc_buf && log_msg_buf) {
749
0
    log_msg_buf = pkg_realloc(log_msg_buf, log_msg_buf_size+1);
750
0
    if (!log_msg_buf) {
751
0
      LM_ERR("no pkg memory left\n");
752
0
      return -1;
753
0
    }
754
0
  } else if (!log_msg_buf) {
755
0
    log_msg_buf = pkg_malloc(log_msg_buf_size+1);
756
0
    if (!log_msg_buf) {
757
0
      LM_ERR("no pkg memory left\n");
758
0
      return -1;
759
0
    }
760
0
  }
761
762
0
  return 0;
763
0
}
764
765
/* replaces the default consumer table with a shm allocated one */
766
int init_log_cons_shm_table(void)
767
0
{
768
0
  struct log_consumer_t *cons;
769
770
0
  cons = shm_malloc(MAX_LOG_CONS_NO * sizeof(struct log_consumer_t));
771
0
  if (!cons) {
772
0
    LM_ERR("no more shm memory\n");
773
0
    return -1;
774
0
  }
775
0
  memset(cons, 0, MAX_LOG_CONS_NO * sizeof(struct log_consumer_t));
776
777
0
  cons[0] = log_consumers[0];
778
0
  cons[1] = log_consumers[1];
779
780
0
  log_consumers = cons;
781
782
0
  return 0;
783
0
}
784
785
void cleanup_log_cons_shm_table(void)
786
0
{
787
0
  struct log_consumer_t *cons = log_consumers;
788
789
0
  log_consumers = default_log_consumers;
790
0
  log_consumers_no = 2;
791
792
  /* even if we are reusing the static default_log_consumers table,
793
   * inherit the latest settings for the consumers */
794
0
  log_consumers[0].level_filter = cons[0].level_filter;
795
0
  log_consumers[0].muted = cons[0].muted;
796
797
0
  log_consumers[1].level_filter = cons[1].level_filter;
798
0
  log_consumers[1].muted = cons[1].muted;
799
800
0
  shm_free(cons);
801
0
}
802
803
int init_log_event_cons(void)
804
0
{
805
0
  evi_log_id = evi_publish_event(evi_log_name);
806
0
  if (evi_log_id == EVI_ERROR) {
807
0
    LM_ERR("cannot register '%.*s' event\n",
808
0
      evi_log_name.len, evi_log_name.s);
809
0
    return -1;
810
0
  }
811
812
0
  log_msg_buf = pkg_malloc(log_msg_buf_size+1);
813
0
  if (!log_msg_buf) {
814
0
    LM_ERR("no pkg memory left\n");
815
0
    return -1;
816
0
  }
817
818
0
  if (register_log_consumer(EVENT_CONSUMER_NAME, event_dprint,
819
0
    log_event_level_filter, 1) < 0) {
820
0
    LM_ERR("Failed to register 'event' log consumer\n");
821
0
    return -1;
822
0
  }
823
824
0
  return 0;
825
0
}
826
827
static struct log_consumer_t *get_log_consumer_by_name(str *name)
828
0
{
829
0
  int i;
830
831
0
  for (i=0; i<log_consumers_no; i++)
832
0
    if (str_match(&log_consumers[i].name, name))
833
0
      return log_consumers+i;
834
835
0
  return NULL;
836
0
}
837
838
int set_log_consumer_level_filter(str *name, int level)
839
0
{
840
0
  struct log_consumer_t *cons;
841
842
0
  cons = get_log_consumer_by_name(name);
843
0
  if (!cons) {
844
0
    LM_ERR("Unknown consumer: %.*s\n", name->len, name->s);
845
0
    return -1;
846
0
  }
847
848
0
  cons->level_filter = level;
849
850
0
  return 0;
851
0
}
852
853
int get_log_consumer_level_filter(str *name, int *level_filter)
854
0
{
855
0
  struct log_consumer_t *cons;
856
857
0
  cons = get_log_consumer_by_name(name);
858
0
  if (!cons) {
859
0
    LM_ERR("Unknown consumer: %.*s\n", name->len, name->s);
860
0
    return -1;
861
0
  }
862
863
0
  *level_filter = cons->level_filter;
864
865
0
  return 0;
866
0
}
867
868
int set_log_consumer_mute_state(str *name, int state)
869
0
{
870
0
  struct log_consumer_t *cons;
871
872
0
  cons = get_log_consumer_by_name(name);
873
0
  if (!cons) {
874
0
    LM_ERR("Unknown consumer: %.*s\n", name->len, name->s);
875
0
    return -1;
876
0
  }
877
878
0
  cons->muted = state;
879
880
0
  return 0;
881
0
}
882
883
int get_log_consumer_mute_state(str *name, int *state)
884
0
{
885
0
  struct log_consumer_t *cons;
886
887
0
  cons = get_log_consumer_by_name(name);
888
0
  if (!cons) {
889
0
    LM_ERR("Unknown consumer: %.*s\n", name->len, name->s);
890
0
    return -1;
891
0
  }
892
893
0
  *state = cons->muted;
894
895
0
  return 0;
896
0
}
897
898
int set_log_event_cons_cfg_state(void)
899
0
{
900
0
  if (set_log_consumer_mute_state(&str_init(EVENT_CONSUMER_NAME),
901
0
    !log_event_enabled) < 0) {
902
0
    LM_ERR("Failed to set mute state for event consumer\n");
903
0
    return -1;
904
0
  }
905
906
0
  return 0;
907
0
}
908
909
void distroy_log_event_cons(void)
910
0
{
911
0
  set_log_consumer_mute_state(&str_init(EVENT_CONSUMER_NAME), 1);
912
0
}
913
914
int init_log_level(void)
915
0
{
916
0
  log_level = &pt[process_no].log_level;
917
0
  default_log_level = &pt[process_no].default_log_level;
918
919
0
  if (process_no==0) {
920
    /* this is done only by the first process */
921
0
    log_level_global = (int*)shm_malloc(sizeof(int));
922
0
    if (log_level_global==NULL) {
923
0
      LM_ERR("Failed to allocate shm memory for global log_level\n");
924
0
      return -1;
925
0
    }
926
0
    *log_level_global = log_level_holder;
927
0
  }
928
929
0
  *log_level = *log_level_global;
930
0
  *default_log_level = *log_level_global;
931
932
0
  return 0;
933
0
}
934
935
/* call before pt is freed */
936
void cleanup_log_level(void)
937
0
{
938
0
  static int my_log_level;
939
940
0
  my_log_level = *log_level;
941
0
  log_level = &my_log_level;
942
0
}
943
944
945
void reset_proc_log_level(void)
946
0
{
947
0
  *log_level = *default_log_level;
948
0
}
949
950
/*
951
 * set the (default) log level of a given process
952
 *
953
 * Note: the index param is not validated!
954
 */
955
void __set_proc_log_level(int proc_idx, int level)
956
0
{
957
0
  pt[proc_idx].log_level = level;
958
0
}
959
960
void __set_proc_default_log_level(int proc_idx, int level)
961
0
{
962
0
  pt[proc_idx].default_log_level = level;
963
0
}
964
965
/* set the current and default log levels for all OpenSIPS processes */
966
void set_global_log_level(int level)
967
0
{
968
0
  int i;
969
970
0
  for (i = 0; i < counted_max_processes; i++) {
971
0
    __set_proc_default_log_level(i, level);
972
0
    __set_proc_log_level(i, level);
973
0
  }
974
0
  *log_level_global = level;
975
0
}
976
977
/* set the log level of the current process */
978
void set_proc_log_level(int level)
979
0
{
980
0
  __set_proc_log_level(process_no, level);
981
0
}
982
983
void suppress_proc_log_event(void)
984
0
{
985
0
  pt[process_no].suppress_log_event = 1;
986
0
}
987
988
void reset_proc_log_event(void)
989
0
{
990
0
  pt[process_no].suppress_log_event = 0;
991
0
}