You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

logger.c 34KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "config.h"
  17. #include "logger.h"
  18. #include "rspamd.h"
  19. #include "map.h"
  20. #include "map_helpers.h"
  21. #include "ottery.h"
  22. #include "unix-std.h"
  23. #ifdef HAVE_SYSLOG_H
  24. #include <syslog.h>
  25. #endif
  26. /* How much message should be repeated before it is count to be repeated one */
  27. #define REPEATS_MIN 3
  28. #define REPEATS_MAX 300
  29. #define LOG_ID 6
  30. #define LOGBUF_LEN 8192
  31. struct rspamd_log_module {
  32. gchar *mname;
  33. guint id;
  34. };
  35. struct rspamd_log_modules {
  36. guchar *bitset;
  37. guint bitset_len; /* Number of BITS used in bitset */
  38. guint bitset_allocated; /* Size of bitset allocated in BYTES */
  39. GHashTable *modules;
  40. };
  41. struct rspamd_logger_error_elt {
  42. gint completed;
  43. GQuark ptype;
  44. pid_t pid;
  45. gdouble ts;
  46. gchar id[LOG_ID + 1];
  47. gchar module[9];
  48. gchar message[];
  49. };
  50. struct rspamd_logger_error_log {
  51. struct rspamd_logger_error_elt *elts;
  52. rspamd_mempool_t *pool;
  53. guint32 max_elts;
  54. guint32 elt_len;
  55. /* Avoid false cache sharing */
  56. guchar __padding[64 - sizeof(gpointer) * 2 - sizeof(guint64)];
  57. guint cur_row;
  58. };
  59. /**
  60. * Static structure that store logging parameters
  61. * It is NOT shared between processes and is created by main process
  62. */
  63. struct rspamd_logger_s {
  64. rspamd_log_func_t log_func;
  65. enum rspamd_log_type log_type;
  66. gint log_facility;
  67. gint log_level;
  68. gchar *log_file;
  69. gboolean log_buffered;
  70. gboolean log_silent_workers;
  71. guint32 log_buf_size;
  72. struct rspamd_logger_error_log *errlog;
  73. struct rspamd_cryptobox_pubkey *pk;
  74. struct rspamd_cryptobox_keypair *keypair;
  75. struct {
  76. guint32 size;
  77. guint32 used;
  78. u_char *buf;
  79. } io_buf;
  80. gint fd;
  81. guint flags;
  82. gboolean is_buffered;
  83. gboolean enabled;
  84. gboolean is_debug;
  85. gboolean throttling;
  86. gboolean no_lock;
  87. gboolean opened;
  88. time_t throttling_time;
  89. enum rspamd_log_type type;
  90. pid_t pid;
  91. guint32 repeats;
  92. GQuark process_type;
  93. struct rspamd_radix_map_helper *debug_ip;
  94. guint64 last_line_cksum;
  95. gchar *saved_message;
  96. gchar *saved_function;
  97. gchar *saved_module;
  98. gchar *saved_id;
  99. rspamd_mempool_mutex_t *mtx;
  100. guint saved_loglevel;
  101. guint64 log_cnt[4];
  102. };
  103. static const gchar lf_chr = '\n';
  104. static rspamd_logger_t *default_logger = NULL;
  105. static struct rspamd_log_modules *log_modules = NULL;
  106. static void syslog_log_function (const gchar *module,
  107. const gchar *id, const gchar *function,
  108. gint log_level, const gchar *message,
  109. gpointer arg);
  110. static void file_log_function (const gchar *module,
  111. const gchar *id, const gchar *function,
  112. gint log_level, const gchar *message,
  113. gpointer arg);
  114. guint rspamd_task_log_id = (guint)-1;
  115. RSPAMD_CONSTRUCTOR(rspamd_task_log_init)
  116. {
  117. rspamd_task_log_id = rspamd_logger_add_debug_module("task");
  118. }
  119. /**
  120. * Calculate checksum for log line (used for repeating logic)
  121. */
  122. static inline guint64
  123. rspamd_log_calculate_cksum (const gchar *message, size_t mlen)
  124. {
  125. return rspamd_cryptobox_fast_hash (message, mlen, rspamd_hash_seed ());
  126. }
  127. /*
  128. * Write a line to log file (unbuffered)
  129. */
  130. static void
  131. direct_write_log_line (rspamd_logger_t *rspamd_log,
  132. void *data,
  133. gsize count,
  134. gboolean is_iov,
  135. gint level_flags)
  136. {
  137. gchar errmsg[128];
  138. struct iovec *iov;
  139. const gchar *line;
  140. glong r;
  141. gint fd;
  142. if (rspamd_log->type == RSPAMD_LOG_CONSOLE) {
  143. if (rspamd_log->flags & RSPAMD_LOG_FLAG_RSPAMADM) {
  144. fd = STDOUT_FILENO;
  145. if (level_flags & G_LOG_LEVEL_CRITICAL) {
  146. fd = STDERR_FILENO;
  147. }
  148. }
  149. else {
  150. fd = STDERR_FILENO;
  151. }
  152. }
  153. else {
  154. fd = rspamd_log->fd;
  155. }
  156. if (!rspamd_log->no_lock) {
  157. #ifndef DISABLE_PTHREAD_MUTEX
  158. if (rspamd_log->mtx) {
  159. rspamd_mempool_lock_mutex (rspamd_log->mtx);
  160. }
  161. else {
  162. rspamd_file_lock (fd, FALSE);
  163. }
  164. #else
  165. rspamd_file_lock (fd, FALSE);
  166. #endif
  167. }
  168. if (is_iov) {
  169. iov = (struct iovec *) data;
  170. r = writev (fd, iov, count);
  171. }
  172. else {
  173. line = (const gchar *) data;
  174. r = write (fd, line, count);
  175. }
  176. if (!rspamd_log->no_lock) {
  177. #ifndef DISABLE_PTHREAD_MUTEX
  178. if (rspamd_log->mtx) {
  179. rspamd_mempool_unlock_mutex (rspamd_log->mtx);
  180. }
  181. else {
  182. rspamd_file_unlock (fd, FALSE);
  183. }
  184. #else
  185. rspamd_file_unlock (fd, FALSE);
  186. #endif
  187. }
  188. if (r == -1) {
  189. /* We cannot write message to file, so we need to detect error and make decision */
  190. if (errno == EINTR) {
  191. /* Try again */
  192. direct_write_log_line (rspamd_log, data, count, is_iov, level_flags);
  193. return;
  194. }
  195. r = rspamd_snprintf (errmsg,
  196. sizeof (errmsg),
  197. "direct_write_log_line: cannot write log line: %s",
  198. strerror (errno));
  199. if (errno == EFAULT || errno == EINVAL || errno == EFBIG ||
  200. errno == ENOSPC) {
  201. /* Rare case */
  202. rspamd_log->throttling = TRUE;
  203. rspamd_log->throttling_time = time (NULL);
  204. }
  205. else if (errno == EPIPE || errno == EBADF) {
  206. /* We write to some pipe and it disappears, disable logging or we has opened bad file descriptor */
  207. rspamd_log->enabled = FALSE;
  208. }
  209. }
  210. else if (rspamd_log->throttling) {
  211. rspamd_log->throttling = FALSE;
  212. }
  213. }
  214. static void
  215. rspamd_escape_log_string (gchar *str)
  216. {
  217. guchar *p = (guchar *) str;
  218. while (*p) {
  219. if ((*p & 0x80) || !g_ascii_isprint (*p)) {
  220. *p = '?';
  221. }
  222. else if (*p == '\n' || *p == '\r') {
  223. *p = ' ';
  224. }
  225. p++;
  226. }
  227. }
  228. /* Logging utility functions */
  229. gint
  230. rspamd_log_open_priv (rspamd_logger_t *rspamd_log, uid_t uid, gid_t gid)
  231. {
  232. if (!rspamd_log->opened) {
  233. switch (rspamd_log->log_type) {
  234. case RSPAMD_LOG_CONSOLE:
  235. /* Do nothing with console */
  236. rspamd_log->fd = -1;
  237. break;
  238. case RSPAMD_LOG_SYSLOG:
  239. #ifdef HAVE_SYSLOG_H
  240. openlog ("rspamd", LOG_NDELAY | LOG_PID,
  241. rspamd_log->log_facility);
  242. #endif
  243. break;
  244. case RSPAMD_LOG_FILE:
  245. rspamd_log->fd = open (rspamd_log->log_file,
  246. O_CREAT | O_WRONLY | O_APPEND,
  247. S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
  248. if (rspamd_log->fd == -1) {
  249. fprintf (stderr,
  250. "open_log: cannot open desired log file: %s, %s my pid: %d",
  251. rspamd_log->log_file, strerror (errno), getpid ());
  252. return -1;
  253. }
  254. if (fchown (rspamd_log->fd, uid, gid) == -1) {
  255. fprintf (stderr,
  256. "open_log: cannot chown desired log file: %s, %s",
  257. rspamd_log->log_file, strerror (errno));
  258. close (rspamd_log->fd);
  259. return -1;
  260. }
  261. break;
  262. default:
  263. return -1;
  264. }
  265. rspamd_log->opened = TRUE;
  266. rspamd_log->enabled = TRUE;
  267. }
  268. return 0;
  269. }
  270. void
  271. rspamd_log_close_priv (rspamd_logger_t *rspamd_log, gboolean termination, uid_t uid, gid_t gid)
  272. {
  273. gchar tmpbuf[256];
  274. rspamd_log_flush (rspamd_log);
  275. if (rspamd_log->opened) {
  276. switch (rspamd_log->type) {
  277. case RSPAMD_LOG_CONSOLE:
  278. /* Do nothing special */
  279. break;
  280. case RSPAMD_LOG_SYSLOG:
  281. #ifdef HAVE_SYSLOG_H
  282. closelog ();
  283. #endif
  284. break;
  285. case RSPAMD_LOG_FILE:
  286. if (rspamd_log->repeats > REPEATS_MIN) {
  287. rspamd_snprintf (tmpbuf,
  288. sizeof (tmpbuf),
  289. "Last message repeated %ud times",
  290. rspamd_log->repeats);
  291. rspamd_log->repeats = 0;
  292. if (rspamd_log->saved_message) {
  293. file_log_function (rspamd_log->saved_module,
  294. rspamd_log->saved_id,
  295. rspamd_log->saved_function,
  296. rspamd_log->saved_loglevel | RSPAMD_LOG_FORCED,
  297. rspamd_log->saved_message,
  298. rspamd_log);
  299. g_free (rspamd_log->saved_message);
  300. g_free (rspamd_log->saved_function);
  301. g_free (rspamd_log->saved_module);
  302. g_free (rspamd_log->saved_id);
  303. rspamd_log->saved_message = NULL;
  304. rspamd_log->saved_function = NULL;
  305. rspamd_log->saved_module = NULL;
  306. rspamd_log->saved_id = NULL;
  307. }
  308. /* It is safe to use temporary buffer here as it is not static */
  309. file_log_function (NULL, NULL,
  310. G_STRFUNC,
  311. rspamd_log->saved_loglevel | RSPAMD_LOG_FORCED,
  312. tmpbuf,
  313. rspamd_log);
  314. }
  315. if (rspamd_log->fd != -1) {
  316. if (fsync (rspamd_log->fd) == -1) {
  317. msg_err ("error syncing log file: %s", strerror (errno));
  318. }
  319. close (rspamd_log->fd);
  320. }
  321. break;
  322. }
  323. rspamd_log->enabled = FALSE;
  324. rspamd_log->opened = FALSE;
  325. }
  326. if (termination && rspamd_log->log_file) {
  327. g_free (rspamd_log->log_file);
  328. rspamd_log->log_file = NULL;
  329. }
  330. }
  331. gint
  332. rspamd_log_reopen_priv (rspamd_logger_t *rspamd_log, uid_t uid, gid_t gid)
  333. {
  334. rspamd_log_close_priv (rspamd_log, FALSE, uid, gid);
  335. if (rspamd_log_open_priv (rspamd_log, uid, gid) == 0) {
  336. msg_info ("log file reopened");
  337. return 0;
  338. }
  339. return -1;
  340. }
  341. /**
  342. * Open log file or initialize other structures
  343. */
  344. gint
  345. rspamd_log_open (rspamd_logger_t *logger)
  346. {
  347. return rspamd_log_open_priv (logger, -1, -1);
  348. }
  349. /**
  350. * Close log file or destroy other structures
  351. */
  352. void
  353. rspamd_log_close (rspamd_logger_t *logger, gboolean termination)
  354. {
  355. rspamd_log_close_priv (logger, termination, -1, -1);
  356. }
  357. /**
  358. * Close and open log again
  359. */
  360. gint
  361. rspamd_log_reopen (rspamd_logger_t *logger)
  362. {
  363. return rspamd_log_reopen_priv (logger, -1, -1);
  364. }
  365. /*
  366. * Setup logger
  367. */
  368. void
  369. rspamd_set_logger (struct rspamd_config *cfg,
  370. GQuark ptype,
  371. rspamd_logger_t **plogger,
  372. rspamd_mempool_t *pool)
  373. {
  374. rspamd_logger_t *logger;
  375. if (plogger == NULL || *plogger == NULL) {
  376. logger = g_malloc0 (sizeof (rspamd_logger_t));
  377. if (cfg->log_error_elts > 0 && pool) {
  378. logger->errlog = rspamd_mempool_alloc0_shared (pool,
  379. sizeof (*logger->errlog));
  380. logger->errlog->pool = pool;
  381. logger->errlog->max_elts = cfg->log_error_elts;
  382. logger->errlog->elt_len = cfg->log_error_elt_maxlen;
  383. logger->errlog->elts = rspamd_mempool_alloc0_shared (pool,
  384. sizeof (struct rspamd_logger_error_elt) * cfg->log_error_elts +
  385. cfg->log_error_elt_maxlen * cfg->log_error_elts);
  386. }
  387. if (pool) {
  388. logger->mtx = rspamd_mempool_get_mutex (pool);
  389. }
  390. if (plogger) {
  391. *plogger = logger;
  392. }
  393. }
  394. else {
  395. logger = *plogger;
  396. }
  397. logger->type = cfg->log_type;
  398. logger->pid = getpid ();
  399. logger->process_type = ptype;
  400. switch (cfg->log_type) {
  401. case RSPAMD_LOG_CONSOLE:
  402. logger->log_func = file_log_function;
  403. logger->fd = -1;
  404. break;
  405. case RSPAMD_LOG_SYSLOG:
  406. logger->log_func = syslog_log_function;
  407. break;
  408. case RSPAMD_LOG_FILE:
  409. logger->log_func = file_log_function;
  410. break;
  411. }
  412. logger->log_type = cfg->log_type;
  413. logger->log_facility = cfg->log_facility;
  414. logger->log_level = cfg->log_level;
  415. logger->log_buffered = cfg->log_buffered;
  416. logger->log_silent_workers = cfg->log_silent_workers;
  417. logger->log_buf_size = cfg->log_buf_size;
  418. if (logger->log_file) {
  419. g_free (logger->log_file);
  420. logger->log_file = NULL;
  421. }
  422. if (cfg->log_file) {
  423. logger->log_file = g_strdup (cfg->log_file);
  424. }
  425. logger->flags = cfg->log_flags;
  426. /* Set up buffer */
  427. if (cfg->log_buffered) {
  428. if (cfg->log_buf_size != 0) {
  429. logger->io_buf.size = cfg->log_buf_size;
  430. }
  431. else {
  432. logger->io_buf.size = LOGBUF_LEN;
  433. }
  434. logger->is_buffered = TRUE;
  435. logger->io_buf.buf = g_malloc (logger->io_buf.size);
  436. }
  437. /* Set up conditional logging */
  438. if (cfg->debug_ip_map != NULL) {
  439. /* Try to add it as map first of all */
  440. if (logger->debug_ip) {
  441. rspamd_map_helper_destroy_radix (logger->debug_ip);
  442. }
  443. logger->debug_ip = NULL;
  444. rspamd_config_radix_from_ucl (cfg,
  445. cfg->debug_ip_map,
  446. "IP addresses for which debug logs are enabled",
  447. &logger->debug_ip, NULL);
  448. }
  449. else if (logger->debug_ip) {
  450. rspamd_map_helper_destroy_radix (logger->debug_ip);
  451. logger->debug_ip = NULL;
  452. }
  453. if (logger->pk) {
  454. rspamd_pubkey_unref (logger->pk);
  455. }
  456. logger->pk = NULL;
  457. if (logger->keypair) {
  458. rspamd_keypair_unref (logger->keypair);
  459. }
  460. logger->keypair = NULL;
  461. if (cfg->log_encryption_key) {
  462. logger->pk = rspamd_pubkey_ref (cfg->log_encryption_key);
  463. logger->keypair = rspamd_keypair_new (RSPAMD_KEYPAIR_KEX,
  464. RSPAMD_CRYPTOBOX_MODE_25519);
  465. rspamd_pubkey_calculate_nm (logger->pk, logger->keypair);
  466. }
  467. default_logger = logger;
  468. }
  469. /**
  470. * Used after fork() for updating structure params
  471. */
  472. void
  473. rspamd_log_update_pid (GQuark ptype, rspamd_logger_t *rspamd_log)
  474. {
  475. rspamd_log->pid = getpid ();
  476. rspamd_log->process_type = ptype;
  477. /* We also need to clear all messages pending */
  478. if (rspamd_log->repeats > 0) {
  479. rspamd_log->repeats = 0;
  480. if (rspamd_log->saved_message) {
  481. g_free (rspamd_log->saved_message);
  482. g_free (rspamd_log->saved_function);
  483. g_free (rspamd_log->saved_module);
  484. g_free (rspamd_log->saved_id);
  485. rspamd_log->saved_message = NULL;
  486. rspamd_log->saved_function = NULL;
  487. rspamd_log->saved_module = NULL;
  488. rspamd_log->saved_id = NULL;
  489. }
  490. }
  491. }
  492. /**
  493. * Flush logging buffer
  494. */
  495. void
  496. rspamd_log_flush (rspamd_logger_t *rspamd_log)
  497. {
  498. if (rspamd_log->is_buffered &&
  499. (rspamd_log->type == RSPAMD_LOG_CONSOLE ||
  500. rspamd_log->type == RSPAMD_LOG_FILE)) {
  501. direct_write_log_line (rspamd_log,
  502. rspamd_log->io_buf.buf,
  503. rspamd_log->io_buf.used,
  504. FALSE, rspamd_log->log_level);
  505. rspamd_log->io_buf.used = 0;
  506. }
  507. }
  508. static inline gboolean
  509. rspamd_logger_need_log (rspamd_logger_t *rspamd_log, GLogLevelFlags log_level,
  510. guint module_id)
  511. {
  512. g_assert (rspamd_log != NULL);
  513. if ((log_level & RSPAMD_LOG_FORCED) || log_level <= rspamd_log->log_level) {
  514. return TRUE;
  515. }
  516. if (module_id != (guint)-1 && isset (log_modules->bitset, module_id)) {
  517. return TRUE;
  518. }
  519. return FALSE;
  520. }
  521. static gchar *
  522. rspamd_log_encrypt_message (const gchar *begin, const gchar *end,
  523. rspamd_logger_t *rspamd_log)
  524. {
  525. guchar *out;
  526. gchar *b64;
  527. guchar *p, *nonce, *mac;
  528. const guchar *comp;
  529. guint len, inlen;
  530. g_assert (end > begin);
  531. /* base64 (pubkey | nonce | message) */
  532. inlen = rspamd_cryptobox_nonce_bytes (RSPAMD_CRYPTOBOX_MODE_25519) +
  533. rspamd_cryptobox_pk_bytes (RSPAMD_CRYPTOBOX_MODE_25519) +
  534. rspamd_cryptobox_mac_bytes (RSPAMD_CRYPTOBOX_MODE_25519) +
  535. (end - begin);
  536. out = g_malloc (inlen);
  537. p = out;
  538. comp = rspamd_pubkey_get_pk (rspamd_log->pk, &len);
  539. memcpy (p, comp, len);
  540. p += len;
  541. ottery_rand_bytes (p, rspamd_cryptobox_nonce_bytes (RSPAMD_CRYPTOBOX_MODE_25519));
  542. nonce = p;
  543. p += rspamd_cryptobox_nonce_bytes (RSPAMD_CRYPTOBOX_MODE_25519);
  544. mac = p;
  545. p += rspamd_cryptobox_mac_bytes (RSPAMD_CRYPTOBOX_MODE_25519);
  546. memcpy (p, begin, end - begin);
  547. comp = rspamd_pubkey_get_nm (rspamd_log->pk, rspamd_log->keypair);
  548. g_assert (comp != NULL);
  549. rspamd_cryptobox_encrypt_nm_inplace (p, end - begin, nonce, comp, mac,
  550. RSPAMD_CRYPTOBOX_MODE_25519);
  551. b64 = rspamd_encode_base64 (out, inlen, 0, NULL);
  552. g_free (out);
  553. return b64;
  554. }
  555. static void
  556. rspamd_log_write_ringbuffer (rspamd_logger_t *rspamd_log,
  557. const gchar *module, const gchar *id,
  558. const gchar *data, glong len)
  559. {
  560. guint32 row_num;
  561. struct rspamd_logger_error_log *elog;
  562. struct rspamd_logger_error_elt *elt;
  563. if (!rspamd_log->errlog) {
  564. return;
  565. }
  566. elog = rspamd_log->errlog;
  567. g_atomic_int_compare_and_exchange (&elog->cur_row, elog->max_elts, 0);
  568. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  569. row_num = g_atomic_int_add (&elog->cur_row, 1);
  570. #else
  571. row_num = g_atomic_int_exchange_and_add (&elog->cur_row, 1);
  572. #endif
  573. if (row_num < elog->max_elts) {
  574. elt = (struct rspamd_logger_error_elt *)(((guchar *)elog->elts) +
  575. (sizeof (*elt) + elog->elt_len) * row_num);
  576. g_atomic_int_set (&elt->completed, 0);
  577. }
  578. else {
  579. /* Race condition */
  580. elog->cur_row = 0;
  581. return;
  582. }
  583. elt->pid = rspamd_log->pid;
  584. elt->ptype = rspamd_log->process_type;
  585. elt->ts = rspamd_get_calendar_ticks ();
  586. if (id) {
  587. rspamd_strlcpy (elt->id, id, sizeof (elt->id));
  588. }
  589. else {
  590. rspamd_strlcpy (elt->id, "", sizeof (elt->id));
  591. }
  592. if (module) {
  593. rspamd_strlcpy (elt->module, module, sizeof (elt->module));
  594. }
  595. else {
  596. rspamd_strlcpy (elt->module, "", sizeof (elt->module));
  597. }
  598. rspamd_strlcpy (elt->message, data, MIN (len + 1, elog->elt_len));
  599. g_atomic_int_set (&elt->completed, 1);
  600. }
  601. void
  602. rspamd_common_logv (rspamd_logger_t *rspamd_log, gint level_flags,
  603. const gchar *module, const gchar *id, const gchar *function,
  604. const gchar *fmt, va_list args)
  605. {
  606. gchar logbuf[RSPAMD_LOGBUF_SIZE], *end;
  607. gint level = level_flags & (RSPAMD_LOG_LEVEL_MASK & G_LOG_LEVEL_MASK), mod_id;
  608. if (G_UNLIKELY (rspamd_log == NULL)) {
  609. rspamd_log = default_logger;
  610. }
  611. if (G_UNLIKELY (rspamd_log == NULL)) {
  612. /* Just fprintf message to stderr */
  613. if (level >= G_LOG_LEVEL_INFO) {
  614. rspamd_vsnprintf (logbuf, sizeof (logbuf), fmt, args);
  615. fprintf (stderr, "%s\n", logbuf);
  616. }
  617. }
  618. else {
  619. if (level == G_LOG_LEVEL_DEBUG) {
  620. mod_id = rspamd_logger_add_debug_module (module);
  621. }
  622. else {
  623. mod_id = -1;
  624. }
  625. if (rspamd_logger_need_log (rspamd_log, level_flags, mod_id)) {
  626. end = rspamd_vsnprintf (logbuf, sizeof (logbuf), fmt, args);
  627. if ((level_flags & RSPAMD_LOG_ENCRYPTED) && rspamd_log->pk) {
  628. gchar *encrypted;
  629. encrypted = rspamd_log_encrypt_message (logbuf, end, rspamd_log);
  630. rspamd_log->log_func (module, id,
  631. function,
  632. level_flags,
  633. encrypted,
  634. rspamd_log);
  635. g_free (encrypted);
  636. }
  637. else {
  638. rspamd_log->log_func (module, id,
  639. function,
  640. level_flags,
  641. logbuf,
  642. rspamd_log);
  643. }
  644. switch (level) {
  645. case G_LOG_LEVEL_CRITICAL:
  646. rspamd_log->log_cnt[0] ++;
  647. rspamd_log_write_ringbuffer (rspamd_log, module, id, logbuf,
  648. end - logbuf);
  649. break;
  650. case G_LOG_LEVEL_WARNING:
  651. rspamd_log->log_cnt[1]++;
  652. break;
  653. case G_LOG_LEVEL_INFO:
  654. rspamd_log->log_cnt[2]++;
  655. break;
  656. case G_LOG_LEVEL_DEBUG:
  657. rspamd_log->log_cnt[3]++;
  658. break;
  659. default:
  660. break;
  661. }
  662. }
  663. }
  664. }
  665. /**
  666. * This log functions select real logger and write message if level is less or equal to configured log level
  667. */
  668. void
  669. rspamd_common_log_function (rspamd_logger_t *rspamd_log,
  670. gint level_flags,
  671. const gchar *module, const gchar *id,
  672. const gchar *function,
  673. const gchar *fmt,
  674. ...)
  675. {
  676. va_list vp;
  677. va_start (vp, fmt);
  678. rspamd_common_logv (rspamd_log, level_flags, module, id, function, fmt, vp);
  679. va_end (vp);
  680. }
  681. void
  682. rspamd_default_logv (gint level_flags, const gchar *module, const gchar *id,
  683. const gchar *function,
  684. const gchar *fmt, va_list args)
  685. {
  686. rspamd_common_logv (NULL, level_flags, module, id, function, fmt, args);
  687. }
  688. void
  689. rspamd_default_log_function (gint level_flags,
  690. const gchar *module, const gchar *id,
  691. const gchar *function, const gchar *fmt, ...)
  692. {
  693. va_list vp;
  694. va_start (vp, fmt);
  695. rspamd_default_logv (level_flags, module, id, function, fmt, vp);
  696. va_end (vp);
  697. }
  698. /**
  699. * Fill buffer with message (limits must be checked BEFORE this call)
  700. */
  701. static void
  702. fill_buffer (rspamd_logger_t *rspamd_log, const struct iovec *iov, gint iovcnt)
  703. {
  704. gint i;
  705. for (i = 0; i < iovcnt; i++) {
  706. memcpy (rspamd_log->io_buf.buf + rspamd_log->io_buf.used,
  707. iov[i].iov_base,
  708. iov[i].iov_len);
  709. rspamd_log->io_buf.used += iov[i].iov_len;
  710. }
  711. }
  712. /*
  713. * Write message to buffer or to file (using direct_write_log_line function)
  714. */
  715. static void
  716. file_log_helper (rspamd_logger_t *rspamd_log,
  717. const struct iovec *iov,
  718. guint iovcnt,
  719. gint level_flags)
  720. {
  721. size_t len = 0;
  722. guint i;
  723. if (!rspamd_log->is_buffered) {
  724. /* Write string directly */
  725. direct_write_log_line (rspamd_log, (void *) iov, iovcnt, TRUE, level_flags);
  726. }
  727. else {
  728. /* Calculate total length */
  729. for (i = 0; i < iovcnt; i++) {
  730. len += iov[i].iov_len;
  731. }
  732. /* Fill buffer */
  733. if (rspamd_log->io_buf.size < len) {
  734. /* Buffer is too small to hold this string, so write it directly */
  735. rspamd_log_flush (rspamd_log);
  736. direct_write_log_line (rspamd_log, (void *) iov, iovcnt, TRUE, level_flags);
  737. }
  738. else if (rspamd_log->io_buf.used + len >= rspamd_log->io_buf.size) {
  739. /* Buffer is full, try to write it directly */
  740. rspamd_log_flush (rspamd_log);
  741. fill_buffer (rspamd_log, iov, iovcnt);
  742. }
  743. else {
  744. /* Copy incoming string to buffer */
  745. fill_buffer (rspamd_log, iov, iovcnt);
  746. }
  747. }
  748. }
  749. /**
  750. * Syslog interface for logging
  751. */
  752. static void
  753. syslog_log_function (const gchar *module, const gchar *id,
  754. const gchar *function,
  755. gint level_flags,
  756. const gchar *message,
  757. gpointer arg)
  758. {
  759. rspamd_logger_t *rspamd_log = arg;
  760. #ifdef HAVE_SYSLOG_H
  761. struct {
  762. GLogLevelFlags glib_level;
  763. gint syslog_level;
  764. } levels_match[] = {
  765. {G_LOG_LEVEL_DEBUG, LOG_DEBUG},
  766. {G_LOG_LEVEL_INFO, LOG_INFO},
  767. {G_LOG_LEVEL_WARNING, LOG_WARNING},
  768. {G_LOG_LEVEL_CRITICAL, LOG_ERR}
  769. };
  770. unsigned i;
  771. gint syslog_level;
  772. if (!(level_flags & RSPAMD_LOG_FORCED) && !rspamd_log->enabled) {
  773. return;
  774. }
  775. /* Detect level */
  776. syslog_level = LOG_DEBUG;
  777. for (i = 0; i < G_N_ELEMENTS (levels_match); i ++) {
  778. if (level_flags & levels_match[i].glib_level) {
  779. syslog_level = levels_match[i].syslog_level;
  780. break;
  781. }
  782. }
  783. syslog (syslog_level, "<%.*s>; %s; %s: %s",
  784. LOG_ID, id != NULL ? id : "",
  785. module != NULL ? module : "",
  786. function != NULL ? function : "",
  787. message);
  788. #endif
  789. }
  790. /**
  791. * Main file interface for logging
  792. */
  793. static void
  794. file_log_function (const gchar *module, const gchar *id,
  795. const gchar *function,
  796. gint level_flags,
  797. const gchar *message,
  798. gpointer arg)
  799. {
  800. static gchar timebuf[64], modulebuf[64];
  801. gchar tmpbuf[256];
  802. gchar *m;
  803. gdouble now;
  804. struct tm tms;
  805. struct iovec iov[5];
  806. gulong r = 0, mr = 0;
  807. guint64 cksum;
  808. size_t mlen, mremain;
  809. const gchar *cptype = NULL;
  810. gboolean got_time = FALSE;
  811. rspamd_logger_t *rspamd_log = arg;
  812. if (!(level_flags & RSPAMD_LOG_FORCED) && !rspamd_log->enabled) {
  813. return;
  814. }
  815. /* Check throttling due to write errors */
  816. if (!(level_flags & RSPAMD_LOG_FORCED) && rspamd_log->throttling) {
  817. now = rspamd_get_calendar_ticks ();
  818. if (rspamd_log->throttling_time != now) {
  819. rspamd_log->throttling_time = now;
  820. got_time = TRUE;
  821. }
  822. else {
  823. /* Do not try to write to file too often while throttling */
  824. return;
  825. }
  826. }
  827. if (!(rspamd_log->flags & RSPAMD_LOG_FLAG_RSPAMADM)) {
  828. /* Check repeats */
  829. mlen = strlen (message);
  830. cksum = rspamd_log_calculate_cksum (message, mlen);
  831. if (cksum == rspamd_log->last_line_cksum) {
  832. rspamd_log->repeats++;
  833. if (rspamd_log->repeats > REPEATS_MIN && rspamd_log->repeats <
  834. REPEATS_MAX) {
  835. /* Do not log anything */
  836. if (rspamd_log->saved_message == NULL) {
  837. rspamd_log->saved_message = g_strdup (message);
  838. rspamd_log->saved_function = g_strdup (function);
  839. if (module) {
  840. rspamd_log->saved_module = g_strdup (module);
  841. }
  842. if (id) {
  843. rspamd_log->saved_id = g_strdup (id);
  844. }
  845. rspamd_log->saved_loglevel = level_flags;
  846. }
  847. return;
  848. }
  849. else if (rspamd_log->repeats > REPEATS_MAX) {
  850. rspamd_snprintf (tmpbuf,
  851. sizeof (tmpbuf),
  852. "Last message repeated %ud times",
  853. rspamd_log->repeats);
  854. rspamd_log->repeats = 0;
  855. /* It is safe to use temporary buffer here as it is not static */
  856. if (rspamd_log->saved_message) {
  857. file_log_function (rspamd_log->saved_module,
  858. rspamd_log->saved_id,
  859. rspamd_log->saved_function,
  860. rspamd_log->saved_loglevel,
  861. rspamd_log->saved_message,
  862. arg);
  863. g_free (rspamd_log->saved_message);
  864. g_free (rspamd_log->saved_function);
  865. g_free (rspamd_log->saved_module);
  866. g_free (rspamd_log->saved_id);
  867. rspamd_log->saved_message = NULL;
  868. rspamd_log->saved_function = NULL;
  869. rspamd_log->saved_module = NULL;
  870. rspamd_log->saved_id = NULL;
  871. }
  872. file_log_function ("logger", NULL,
  873. G_STRFUNC,
  874. rspamd_log->saved_loglevel,
  875. tmpbuf,
  876. arg);
  877. file_log_function (module, id,
  878. function,
  879. level_flags,
  880. message,
  881. arg);
  882. rspamd_log->repeats = REPEATS_MIN + 1;
  883. return;
  884. }
  885. }
  886. else {
  887. /* Reset counter if new message differs from saved message */
  888. rspamd_log->last_line_cksum = cksum;
  889. if (rspamd_log->repeats > REPEATS_MIN) {
  890. rspamd_snprintf (tmpbuf,
  891. sizeof (tmpbuf),
  892. "Last message repeated %ud times",
  893. rspamd_log->repeats);
  894. rspamd_log->repeats = 0;
  895. if (rspamd_log->saved_message) {
  896. file_log_function (rspamd_log->saved_module,
  897. rspamd_log->saved_id,
  898. rspamd_log->saved_function,
  899. rspamd_log->saved_loglevel,
  900. rspamd_log->saved_message,
  901. arg);
  902. g_free (rspamd_log->saved_message);
  903. g_free (rspamd_log->saved_function);
  904. g_free (rspamd_log->saved_module);
  905. g_free (rspamd_log->saved_id);
  906. rspamd_log->saved_message = NULL;
  907. rspamd_log->saved_function = NULL;
  908. rspamd_log->saved_module = NULL;
  909. rspamd_log->saved_id = NULL;
  910. }
  911. file_log_function ("logger", NULL,
  912. G_STRFUNC,
  913. level_flags,
  914. tmpbuf,
  915. arg);
  916. /* It is safe to use temporary buffer here as it is not static */
  917. file_log_function (module, id,
  918. function,
  919. level_flags,
  920. message,
  921. arg);
  922. return;
  923. }
  924. else {
  925. rspamd_log->repeats = 0;
  926. }
  927. }
  928. if (!got_time) {
  929. now = rspamd_get_calendar_ticks ();
  930. }
  931. /* Format time */
  932. if (!(rspamd_log->flags & RSPAMD_LOG_FLAG_SYSTEMD)) {
  933. time_t sec = now;
  934. gsize r;
  935. rspamd_localtime (sec, &tms);
  936. r = strftime (timebuf, sizeof (timebuf), "%F %H:%M:%S", &tms);
  937. if (rspamd_log->flags & RSPAMD_LOG_FLAG_USEC) {
  938. gchar usec_buf[16];
  939. rspamd_snprintf (usec_buf, sizeof (usec_buf), "%.5f",
  940. now - (gdouble)sec);
  941. rspamd_snprintf (timebuf + r, sizeof (timebuf) - r,
  942. "%s", usec_buf + 1);
  943. }
  944. }
  945. cptype = g_quark_to_string (rspamd_log->process_type);
  946. if (rspamd_log->flags & RSPAMD_LOG_FLAG_COLOR) {
  947. if (level_flags & (G_LOG_LEVEL_INFO|G_LOG_LEVEL_MESSAGE)) {
  948. /* White */
  949. r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[0;37m");
  950. }
  951. else if (level_flags & G_LOG_LEVEL_WARNING) {
  952. /* Magenta */
  953. r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[0;32m");
  954. }
  955. else if (level_flags & G_LOG_LEVEL_CRITICAL) {
  956. /* Red */
  957. r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[1;31m");
  958. }
  959. }
  960. else {
  961. r = 0;
  962. }
  963. if (!(rspamd_log->flags & RSPAMD_LOG_FLAG_SYSTEMD)) {
  964. r += rspamd_snprintf (tmpbuf + r,
  965. sizeof (tmpbuf) - r,
  966. "%s #%P(%s) ",
  967. timebuf,
  968. rspamd_log->pid,
  969. cptype);
  970. }
  971. else {
  972. r += rspamd_snprintf (tmpbuf + r,
  973. sizeof (tmpbuf) - r,
  974. "(%s) ",
  975. cptype);
  976. }
  977. modulebuf[0] = '\0';
  978. mremain = sizeof (modulebuf);
  979. m = modulebuf;
  980. if (id != NULL) {
  981. guint slen = strlen (id);
  982. slen = MIN (LOG_ID, slen);
  983. mr = rspamd_snprintf (m, mremain, "<%*.s>; ", slen,
  984. id);
  985. m += mr;
  986. mremain -= mr;
  987. }
  988. if (module != NULL) {
  989. mr = rspamd_snprintf (m, mremain, "%s; ", module);
  990. m += mr;
  991. mremain -= mr;
  992. }
  993. if (function != NULL) {
  994. mr = rspamd_snprintf (m, mremain, "%s: ", function);
  995. m += mr;
  996. mremain -= mr;
  997. }
  998. else {
  999. mr = rspamd_snprintf (m, mremain, ": ");
  1000. m += mr;
  1001. mremain -= mr;
  1002. }
  1003. /* Construct IOV for log line */
  1004. iov[0].iov_base = tmpbuf;
  1005. iov[0].iov_len = r;
  1006. iov[1].iov_base = modulebuf;
  1007. iov[1].iov_len = m - modulebuf;
  1008. iov[2].iov_base = (void *) message;
  1009. iov[2].iov_len = mlen;
  1010. iov[3].iov_base = (void *) &lf_chr;
  1011. iov[3].iov_len = 1;
  1012. if (rspamd_log->flags & RSPAMD_LOG_FLAG_COLOR) {
  1013. iov[4].iov_base = "\033[0m";
  1014. iov[4].iov_len = sizeof ("\033[0m") - 1;
  1015. /* Call helper (for buffering) */
  1016. file_log_helper (rspamd_log, iov, 5, level_flags);
  1017. }
  1018. else {
  1019. /* Call helper (for buffering) */
  1020. file_log_helper (rspamd_log, iov, 4, level_flags);
  1021. }
  1022. }
  1023. else {
  1024. /* Rspamadm logging version */
  1025. mlen = strlen (message);
  1026. if (rspamd_log->flags & RSPAMD_LOG_FLAG_COLOR) {
  1027. if (level_flags & (G_LOG_LEVEL_INFO|G_LOG_LEVEL_MESSAGE)) {
  1028. /* White */
  1029. r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[0;37m");
  1030. }
  1031. else if (level_flags & G_LOG_LEVEL_WARNING) {
  1032. /* Magenta */
  1033. r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[0;32m");
  1034. }
  1035. else if (level_flags & G_LOG_LEVEL_CRITICAL) {
  1036. /* Red */
  1037. r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[1;31m");
  1038. }
  1039. iov[0].iov_base = (void *) tmpbuf;
  1040. iov[0].iov_len = r;
  1041. iov[1].iov_base = (void *) message;
  1042. iov[1].iov_len = mlen;
  1043. r = 2;
  1044. }
  1045. else {
  1046. iov[0].iov_base = (void *) message;
  1047. iov[0].iov_len = mlen;
  1048. r = 1;
  1049. }
  1050. iov[r].iov_base = (void *) &lf_chr;
  1051. iov[r++].iov_len = 1;
  1052. if (rspamd_log->flags & RSPAMD_LOG_FLAG_COLOR) {
  1053. iov[r].iov_base = "\033[0m";
  1054. iov[r++].iov_len = sizeof ("\033[0m") - 1;
  1055. /* Call helper (for buffering) */
  1056. file_log_helper (rspamd_log, iov, r, level_flags);
  1057. }
  1058. else {
  1059. /* Call helper (for buffering) */
  1060. file_log_helper (rspamd_log, iov, r, level_flags);
  1061. }
  1062. }
  1063. }
  1064. /**
  1065. * Write log line depending on ip
  1066. */
  1067. void
  1068. rspamd_conditional_debug (rspamd_logger_t *rspamd_log,
  1069. rspamd_inet_addr_t *addr, const gchar *module, const gchar *id,
  1070. const gchar *function, const gchar *fmt, ...)
  1071. {
  1072. static gchar logbuf[LOGBUF_LEN];
  1073. va_list vp;
  1074. gchar *end;
  1075. guint mod_id;
  1076. if (rspamd_log == NULL) {
  1077. rspamd_log = default_logger;
  1078. }
  1079. mod_id = rspamd_logger_add_debug_module (module);
  1080. if (rspamd_logger_need_log (rspamd_log, G_LOG_LEVEL_DEBUG, mod_id) ||
  1081. rspamd_log->is_debug) {
  1082. if (rspamd_log->debug_ip && addr != NULL) {
  1083. if (rspamd_match_radix_map_addr (rspamd_log->debug_ip,
  1084. addr) == NULL) {
  1085. return;
  1086. }
  1087. }
  1088. va_start (vp, fmt);
  1089. end = rspamd_vsnprintf (logbuf, sizeof (logbuf), fmt, vp);
  1090. *end = '\0';
  1091. va_end (vp);
  1092. rspamd_log->log_func (module, id,
  1093. function,
  1094. G_LOG_LEVEL_DEBUG | RSPAMD_LOG_FORCED,
  1095. logbuf,
  1096. rspamd_log);
  1097. }
  1098. }
  1099. void
  1100. rspamd_conditional_debug_fast (rspamd_logger_t *rspamd_log,
  1101. rspamd_inet_addr_t *addr,
  1102. guint mod_id, const gchar *module, const gchar *id,
  1103. const gchar *function, const gchar *fmt, ...)
  1104. {
  1105. static gchar logbuf[LOGBUF_LEN];
  1106. va_list vp;
  1107. gchar *end;
  1108. if (rspamd_log == NULL) {
  1109. rspamd_log = default_logger;
  1110. }
  1111. if (rspamd_logger_need_log (rspamd_log, G_LOG_LEVEL_DEBUG, mod_id) ||
  1112. rspamd_log->is_debug) {
  1113. if (rspamd_log->debug_ip && addr != NULL) {
  1114. if (rspamd_match_radix_map_addr (rspamd_log->debug_ip, addr)
  1115. == NULL) {
  1116. return;
  1117. }
  1118. }
  1119. va_start (vp, fmt);
  1120. end = rspamd_vsnprintf (logbuf, sizeof (logbuf), fmt, vp);
  1121. *end = '\0';
  1122. va_end (vp);
  1123. rspamd_log->log_func (module, id,
  1124. function,
  1125. G_LOG_LEVEL_DEBUG | RSPAMD_LOG_FORCED,
  1126. logbuf,
  1127. rspamd_log);
  1128. }
  1129. }
  1130. /**
  1131. * Wrapper for glib logger
  1132. */
  1133. void
  1134. rspamd_glib_log_function (const gchar *log_domain,
  1135. GLogLevelFlags log_level,
  1136. const gchar *message,
  1137. gpointer arg)
  1138. {
  1139. rspamd_logger_t *rspamd_log = arg;
  1140. if (rspamd_log->enabled &&
  1141. rspamd_logger_need_log (rspamd_log, log_level, -1)) {
  1142. rspamd_log->log_func ("glib", NULL,
  1143. NULL,
  1144. log_level,
  1145. message,
  1146. rspamd_log);
  1147. }
  1148. }
  1149. void
  1150. rspamd_glib_printerr_function (const gchar *message)
  1151. {
  1152. rspamd_common_log_function (NULL, G_LOG_LEVEL_CRITICAL, "glib",
  1153. NULL, G_STRFUNC,
  1154. "%s", message);
  1155. }
  1156. /**
  1157. * Temporary turn on debugging
  1158. */
  1159. void
  1160. rspamd_log_debug (rspamd_logger_t *rspamd_log)
  1161. {
  1162. rspamd_log->is_debug = TRUE;
  1163. }
  1164. /**
  1165. * Turn off temporary debugging
  1166. */
  1167. void
  1168. rspamd_log_nodebug (rspamd_logger_t *rspamd_log)
  1169. {
  1170. rspamd_log->is_debug = FALSE;
  1171. }
  1172. const guint64 *
  1173. rspamd_log_counters (rspamd_logger_t *logger)
  1174. {
  1175. if (logger) {
  1176. return logger->log_cnt;
  1177. }
  1178. return NULL;
  1179. }
  1180. void
  1181. rspamd_log_nolock (rspamd_logger_t *logger)
  1182. {
  1183. if (logger) {
  1184. logger->no_lock = TRUE;
  1185. }
  1186. }
  1187. void
  1188. rspamd_log_lock (rspamd_logger_t *logger)
  1189. {
  1190. if (logger) {
  1191. logger->no_lock = FALSE;
  1192. }
  1193. }
  1194. static gint
  1195. rspamd_log_errlog_cmp (const ucl_object_t **o1, const ucl_object_t **o2)
  1196. {
  1197. const ucl_object_t *ts1, *ts2;
  1198. ts1 = ucl_object_lookup (*o1, "ts");
  1199. ts2 = ucl_object_lookup (*o2, "ts");
  1200. if (ts1 && ts2) {
  1201. gdouble t1 = ucl_object_todouble (ts1), t2 = ucl_object_todouble (ts2);
  1202. if (t1 > t2) {
  1203. return -1;
  1204. }
  1205. else if (t2 > t1) {
  1206. return 1;
  1207. }
  1208. }
  1209. return 0;
  1210. }
  1211. ucl_object_t *
  1212. rspamd_log_errorbuf_export (const rspamd_logger_t *logger)
  1213. {
  1214. struct rspamd_logger_error_elt *cpy, *cur;
  1215. ucl_object_t *top = ucl_object_typed_new (UCL_ARRAY);
  1216. guint i;
  1217. if (logger->errlog == NULL) {
  1218. return top;
  1219. }
  1220. cpy = g_malloc0_n (logger->errlog->max_elts,
  1221. sizeof (*cpy) + logger->errlog->elt_len);
  1222. memcpy (cpy, logger->errlog->elts, logger->errlog->max_elts *
  1223. (sizeof (*cpy) + logger->errlog->elt_len));
  1224. for (i = 0; i < logger->errlog->max_elts; i ++) {
  1225. cur = (struct rspamd_logger_error_elt *)((guchar *)cpy +
  1226. i * ((sizeof (*cpy) + logger->errlog->elt_len)));
  1227. if (cur->completed) {
  1228. ucl_object_t *obj = ucl_object_typed_new (UCL_OBJECT);
  1229. ucl_object_insert_key (obj, ucl_object_fromdouble (cur->ts),
  1230. "ts", 0, false);
  1231. ucl_object_insert_key (obj, ucl_object_fromint (cur->pid),
  1232. "pid", 0, false);
  1233. ucl_object_insert_key (obj,
  1234. ucl_object_fromstring (g_quark_to_string (cur->ptype)),
  1235. "type", 0, false);
  1236. ucl_object_insert_key (obj, ucl_object_fromstring (cur->id),
  1237. "id", 0, false);
  1238. ucl_object_insert_key (obj, ucl_object_fromstring (cur->module),
  1239. "module", 0, false);
  1240. ucl_object_insert_key (obj, ucl_object_fromstring (cur->message),
  1241. "message", 0, false);
  1242. ucl_array_append (top, obj);
  1243. }
  1244. }
  1245. ucl_object_array_sort (top, rspamd_log_errlog_cmp);
  1246. g_free (cpy);
  1247. return top;
  1248. }
  1249. static guint
  1250. rspamd_logger_allocate_mod_bit (void)
  1251. {
  1252. if (log_modules->bitset_allocated * NBBY > log_modules->bitset_len + 1) {
  1253. log_modules->bitset_len ++;
  1254. return log_modules->bitset_len - 1;
  1255. }
  1256. else {
  1257. /* Need to expand */
  1258. log_modules->bitset_allocated *= 2;
  1259. log_modules->bitset = g_realloc (log_modules->bitset,
  1260. log_modules->bitset_allocated);
  1261. return rspamd_logger_allocate_mod_bit ();
  1262. }
  1263. }
  1264. guint
  1265. rspamd_logger_add_debug_module (const gchar *mname)
  1266. {
  1267. struct rspamd_log_module *m;
  1268. if (mname == NULL) {
  1269. return (guint)-1;
  1270. }
  1271. if (log_modules == NULL) {
  1272. log_modules = g_malloc0 (sizeof (*log_modules));
  1273. log_modules->modules = g_hash_table_new (rspamd_strcase_hash,
  1274. rspamd_strcase_equal);
  1275. log_modules->bitset_allocated = 16;
  1276. log_modules->bitset_len = 0;
  1277. log_modules->bitset = g_malloc0 (log_modules->bitset_allocated);
  1278. }
  1279. if ((m = g_hash_table_lookup (log_modules->modules, mname)) == NULL) {
  1280. m = g_malloc0 (sizeof (*m));
  1281. m->mname = g_strdup (mname);
  1282. m->id = rspamd_logger_allocate_mod_bit ();
  1283. clrbit (log_modules->bitset, m->id);
  1284. g_hash_table_insert (log_modules->modules, m->mname, m);
  1285. }
  1286. return m->id;
  1287. }
  1288. void
  1289. rspamd_logger_configure_modules (GHashTable *mods_enabled)
  1290. {
  1291. GHashTableIter it;
  1292. gpointer k, v;
  1293. guint id;
  1294. /* On first iteration, we go through all modules enabled and add missing ones */
  1295. g_hash_table_iter_init (&it, mods_enabled);
  1296. while (g_hash_table_iter_next (&it, &k, &v)) {
  1297. rspamd_logger_add_debug_module ((const gchar *)k);
  1298. }
  1299. g_hash_table_iter_init (&it, mods_enabled);
  1300. while (g_hash_table_iter_next (&it, &k, &v)) {
  1301. id = rspamd_logger_add_debug_module ((const gchar *)k);
  1302. if (isclr (log_modules->bitset, id)) {
  1303. msg_info ("enable debugging for module %s (%d)", (const gchar *) k,
  1304. id);
  1305. setbit (log_modules->bitset, id);
  1306. }
  1307. }
  1308. }