Coverage Report

Created: 2026-10-28 06:08

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