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.

util.h 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. #ifndef RSPAMD_UTIL_H
  2. #define RSPAMD_UTIL_H
  3. #include "config.h"
  4. #include "mem_pool.h"
  5. #include "printf.h"
  6. #include "fstring.h"
  7. #include "addr.h"
  8. #include "str_util.h"
  9. #ifdef HAVE_NETDB_H
  10. #include <netdb.h>
  11. #endif
  12. #include "contrib/libev/ev.h"
  13. #include <time.h>
  14. #ifdef __cplusplus
  15. extern "C" {
  16. #endif
  17. struct rspamd_config;
  18. enum rspamd_exception_type {
  19. RSPAMD_EXCEPTION_NEWLINE = 0,
  20. RSPAMD_EXCEPTION_URL,
  21. RSPAMD_EXCEPTION_GENERIC,
  22. };
  23. /**
  24. * Structure to point exception in text from processing
  25. */
  26. struct rspamd_process_exception {
  27. goffset pos;
  28. guint len;
  29. gpointer ptr;
  30. enum rspamd_exception_type type;
  31. };
  32. /**
  33. * Create generic socket
  34. * @param af address family
  35. * @param type socket type
  36. * @param protocol socket protocol
  37. * @param async set non-blocking on a socket
  38. * @return socket FD or -1 in case of error
  39. */
  40. gint rspamd_socket_create (gint af, gint type, gint protocol, gboolean async);
  41. /*
  42. * Create socket and bind or connect it to specified address and port
  43. */
  44. gint rspamd_socket_tcp (struct addrinfo *, gboolean is_server, gboolean async);
  45. /*
  46. * Create socket and bind or connect it to specified address and port
  47. */
  48. gint rspamd_socket_udp (struct addrinfo *, gboolean is_server, gboolean async);
  49. /*
  50. * Create and bind or connect unix socket
  51. */
  52. gint rspamd_socket_unix (const gchar *,
  53. struct sockaddr_un *,
  54. gint type,
  55. gboolean is_server,
  56. gboolean async);
  57. /**
  58. * Make a universal socket
  59. * @param credits host, ip or path to unix socket
  60. * @param port port (used for network sockets)
  61. * @param type type of socket (SO_STREAM or SO_DGRAM)
  62. * @param async make this socket async
  63. * @param is_server make this socket as server socket
  64. * @param try_resolve try name resolution for a socket (BLOCKING)
  65. */
  66. gint rspamd_socket (const gchar *credits, guint16 port, gint type,
  67. gboolean async, gboolean is_server, gboolean try_resolve);
  68. /*
  69. * Create socketpair
  70. */
  71. gboolean rspamd_socketpair (gint pair[2], gint af);
  72. /*
  73. * Make specified socket non-blocking
  74. */
  75. gint rspamd_socket_nonblocking (gint);
  76. /*
  77. * Make specified socket blocking
  78. */
  79. gint rspamd_socket_blocking (gint);
  80. /*
  81. * Poll a sync socket for specified events
  82. */
  83. gint rspamd_socket_poll (gint fd, gint timeout, short events);
  84. /*
  85. * Init signals
  86. */
  87. #ifdef HAVE_SA_SIGINFO
  88. void rspamd_signals_init (struct sigaction *sa, void (*sig_handler) (gint,
  89. siginfo_t *,
  90. void *));
  91. #else
  92. void rspamd_signals_init (struct sigaction *sa, void (*sig_handler)(gint));
  93. #endif
  94. #ifndef HAVE_SETPROCTITLE
  95. /*
  96. * Process title utility functions
  97. */
  98. gint init_title (rspamd_mempool_t *pool, gint argc, gchar *argv[], gchar *envp[]);
  99. gint setproctitle (const gchar *fmt, ...);
  100. #endif
  101. #ifndef HAVE_PIDFILE
  102. /*
  103. * Pidfile functions from FreeBSD libutil code
  104. */
  105. typedef struct rspamd_pidfh_s {
  106. gint pf_fd;
  107. #ifdef HAVE_PATH_MAX
  108. gchar pf_path[PATH_MAX + 1];
  109. #elif defined(HAVE_MAXPATHLEN)
  110. gchar pf_path[MAXPATHLEN + 1];
  111. #else
  112. gchar pf_path[1024 + 1];
  113. #endif
  114. dev_t pf_dev;
  115. ino_t pf_ino;
  116. } rspamd_pidfh_t;
  117. rspamd_pidfh_t *rspamd_pidfile_open (const gchar *path,
  118. mode_t mode,
  119. pid_t *pidptr);
  120. gint rspamd_pidfile_write (rspamd_pidfh_t *pfh);
  121. gint rspamd_pidfile_close (rspamd_pidfh_t *pfh);
  122. gint rspamd_pidfile_remove (rspamd_pidfh_t *pfh);
  123. #else
  124. typedef struct pidfh rspamd_pidfh_t;
  125. #define rspamd_pidfile_open pidfile_open
  126. #define rspamd_pidfile_write pidfile_write
  127. #define rspamd_pidfile_close pidfile_close
  128. #define rspamd_pidfile_remove pidfile_remove
  129. #endif
  130. /*
  131. * Replace %r with rcpt value and %f with from value, new string is allocated in pool
  132. */
  133. gchar *resolve_stat_filename (rspamd_mempool_t *pool,
  134. gchar *pattern,
  135. gchar *rcpt,
  136. gchar *from);
  137. const gchar *
  138. rspamd_log_check_time (gdouble start, gdouble end, gint resolution);
  139. /*
  140. * File locking functions
  141. */
  142. gboolean rspamd_file_lock (gint fd, gboolean async);
  143. gboolean rspamd_file_unlock (gint fd, gboolean async);
  144. /*
  145. * Workarounds for older versions of glib
  146. */
  147. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 22))
  148. void g_ptr_array_unref (GPtrArray *array);
  149. gboolean g_int64_equal (gconstpointer v1, gconstpointer v2);
  150. guint g_int64_hash (gconstpointer v);
  151. #endif
  152. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 14))
  153. void g_queue_clear (GQueue *queue);
  154. #endif
  155. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 32))
  156. void g_queue_free_full (GQueue *queue, GDestroyNotify free_func);
  157. #endif
  158. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 40))
  159. void g_ptr_array_insert (GPtrArray *array, gint index_, gpointer data);
  160. #endif
  161. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 30))
  162. GPtrArray* g_ptr_array_new_full (guint reserved_size,
  163. GDestroyNotify element_free_func);
  164. #endif
  165. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 32))
  166. const gchar *g_environ_getenv (gchar **envp, const gchar *variable);
  167. #endif
  168. /*
  169. * Convert milliseconds to timeval fields
  170. */
  171. #define msec_to_tv(msec, tv) do { (tv)->tv_sec = (msec) / 1000; (tv)->tv_usec = \
  172. ((msec) - (tv)->tv_sec * 1000) * 1000; \
  173. } while (0)
  174. #define double_to_tv(dbl, tv) do { (tv)->tv_sec = (int)(dbl); (tv)->tv_usec = \
  175. ((dbl) - (int)(dbl)) * 1000 * 1000; \
  176. } while (0)
  177. #define double_to_ts(dbl, ts) do { (ts)->tv_sec = (int)(dbl); (ts)->tv_nsec = \
  178. ((dbl) - (int)(dbl)) * 1e9; \
  179. } while (0)
  180. #define tv_to_msec(tv) ((tv)->tv_sec * 1000LLU + (tv)->tv_usec / 1000LLU)
  181. #define tv_to_double(tv) ((double)(tv)->tv_sec + (tv)->tv_usec / 1.0e6)
  182. #define ts_to_usec(ts) ((ts)->tv_sec * 1000000LLU + \
  183. (ts)->tv_nsec / 1000LLU)
  184. #define ts_to_double(tv) ((double)(tv)->tv_sec + (tv)->tv_nsec / 1.0e9)
  185. /**
  186. * Try to allocate a file on filesystem (using fallocate or posix_fallocate)
  187. * @param fd descriptor
  188. * @param offset offset of file
  189. * @param len length to allocate
  190. * @return -1 in case of failure
  191. */
  192. gint rspamd_fallocate (gint fd, off_t offset, off_t len);
  193. /**
  194. * Utils for working with threads to be compatible with all glib versions
  195. */
  196. typedef struct rspamd_mutex_s {
  197. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  198. GMutex mtx;
  199. #else
  200. GStaticMutex mtx;
  201. #endif
  202. } rspamd_mutex_t;
  203. /**
  204. * Create new mutex
  205. * @return mutex or NULL
  206. */
  207. rspamd_mutex_t *rspamd_mutex_new (void);
  208. /**
  209. * Lock mutex
  210. * @param mtx
  211. */
  212. void rspamd_mutex_lock (rspamd_mutex_t *mtx);
  213. /**
  214. * Unlock mutex
  215. * @param mtx
  216. */
  217. void rspamd_mutex_unlock (rspamd_mutex_t *mtx);
  218. /**
  219. * Clear rspamd mutex
  220. * @param mtx
  221. */
  222. void rspamd_mutex_free (rspamd_mutex_t *mtx);
  223. /**
  224. * Deep copy of one hash table to another
  225. * @param src source hash
  226. * @param dst destination hash
  227. * @param key_copy_func function called to copy or modify keys (or NULL)
  228. * @param value_copy_func function called to copy or modify values (or NULL)
  229. * @param ud user data for copy functions
  230. */
  231. void rspamd_hash_table_copy (GHashTable *src, GHashTable *dst,
  232. gpointer (*key_copy_func) (gconstpointer data, gpointer ud),
  233. gpointer (*value_copy_func) (gconstpointer data, gpointer ud),
  234. gpointer ud);
  235. /**
  236. * Read passphrase from tty
  237. * @param buf buffer to fill with a password
  238. * @param size size of the buffer
  239. * @param rwflag unused flag
  240. * @param key unused key
  241. * @return size of password read
  242. */
  243. gint rspamd_read_passphrase (gchar *buf, gint size, gint rwflag, gpointer key);
  244. /**
  245. * Portably return the current clock ticks as seconds
  246. * @return
  247. */
  248. gdouble rspamd_get_ticks (gboolean rdtsc_ok);
  249. /**
  250. * Portably return the current virtual clock ticks as seconds
  251. * @return
  252. */
  253. gdouble rspamd_get_virtual_ticks (void);
  254. /**
  255. * Return the real timestamp as unixtime
  256. */
  257. gdouble rspamd_get_calendar_ticks (void);
  258. /**
  259. * Special utility to help array freeing in rspamd_mempool
  260. * @param p
  261. */
  262. void rspamd_ptr_array_free_hard (gpointer p);
  263. /**
  264. * Special utility to help array freeing in rspamd_mempool
  265. * @param p
  266. */
  267. void rspamd_array_free_hard (gpointer p);
  268. /**
  269. * Special utility to help GString freeing in rspamd_mempool
  270. * @param p
  271. */
  272. void rspamd_gstring_free_hard (gpointer p);
  273. /**
  274. * Special utility to help GError freeing in rspamd_mempool
  275. * @param p
  276. */
  277. void rspamd_gerror_free_maybe (gpointer p);
  278. /**
  279. * Special utility to help GString freeing (without freeing the memory segment) in rspamd_mempool
  280. * @param p
  281. */
  282. void rspamd_gstring_free_soft (gpointer p);
  283. /**
  284. * Returns some statically initialized random hash seed
  285. * @return hash seed
  286. */
  287. guint64 rspamd_hash_seed (void);
  288. /**
  289. * Returns random hex string of the specified length
  290. * @param buf
  291. * @param len
  292. */
  293. void rspamd_random_hex (guchar *buf, guint64 len);
  294. /**
  295. * Returns
  296. * @param pattern pattern to create (should end with some number of X symbols), modified by this function
  297. * @return
  298. */
  299. gint rspamd_shmem_mkstemp (gchar *pattern);
  300. /**
  301. * Return jittered time value
  302. */
  303. gdouble rspamd_time_jitter (gdouble in, gdouble jitter);
  304. /**
  305. * Return random double in range [0..1)
  306. * @return
  307. */
  308. gdouble rspamd_random_double (void);
  309. /**
  310. * Return random double in range [0..1) using xoroshiro128+ algorithm (not crypto secure)
  311. * @return
  312. */
  313. gdouble rspamd_random_double_fast (void);
  314. gdouble rspamd_random_double_fast_seed (guint64 seed[4]);
  315. guint64 rspamd_random_uint64_fast (void);
  316. /**
  317. * Seed fast rng
  318. */
  319. void rspamd_random_seed_fast (void);
  320. /**
  321. * Constant time version of memcmp
  322. */
  323. gboolean rspamd_constant_memcmp (const void *a, const void *b, gsize len);
  324. /**
  325. * Open file without following symlinks or special stuff
  326. * @param fname filename
  327. * @param oflags open flags
  328. * @param mode mode to open
  329. * @return fd or -1 in case of error
  330. */
  331. int rspamd_file_xopen (const char *fname, int oflags, guint mode,
  332. gboolean allow_symlink);
  333. /**
  334. * Map file without following symlinks or special stuff
  335. * @param fname filename
  336. * @param mode mode to open
  337. * @param size target size (must NOT be NULL)
  338. * @return pointer to memory (should be freed using munmap) or NULL in case of error
  339. */
  340. gpointer rspamd_file_xmap (const char *fname, guint mode, gsize *size,
  341. gboolean allow_symlink);
  342. /**
  343. * Map named shared memory segment
  344. * @param fname filename
  345. * @param mode mode to open
  346. * @param size target size (must NOT be NULL)
  347. * @return pointer to memory (should be freed using munmap) or NULL in case of error
  348. */
  349. gpointer rspamd_shmem_xmap (const char *fname, guint mode,
  350. gsize *size);
  351. /**
  352. * Normalize probabilities using polynomial function
  353. * @param x probability (bias .. 1)
  354. * @return
  355. */
  356. gdouble rspamd_normalize_probability (gdouble x, gdouble bias);
  357. /**
  358. * Converts struct tm to time_t
  359. * @param tm
  360. * @param tz timezone in format (hours * 100) + minutes
  361. * @return
  362. */
  363. guint64 rspamd_tm_to_time (const struct tm *tm, glong tz);
  364. /**
  365. * Splits unix timestamp into struct tm using GMT timezone
  366. * @param ts
  367. * @param dest
  368. */
  369. void rspamd_gmtime (gint64 ts, struct tm *dest);
  370. /**
  371. * Split unix timestamp into struct tm using local timezone
  372. * @param ts
  373. * @param dest
  374. */
  375. void rspamd_localtime (gint64 ts, struct tm *dest);
  376. #define PTR_ARRAY_FOREACH(ar, i, cur) for ((i) = 0; (ar) != NULL && (i) < (ar)->len && (((cur) = (__typeof__(cur))g_ptr_array_index((ar), (i))) || 1); ++(i))
  377. /**
  378. * Compresses the input string using gzip+zlib. Old string is replaced and freed
  379. * if compressed. If not compressed it is untouched.
  380. * @param in
  381. * @return TRUE if a string has been compressed
  382. */
  383. gboolean rspamd_fstring_gzip (rspamd_fstring_t **in);
  384. /**
  385. * Perform globbing searching for the specified path. Allow recursion,
  386. * returns an error if maximum nesting is reached.
  387. * @param pattern
  388. * @param recursive
  389. * @param err
  390. * @return GPtrArray of gchar *, elements are freed when array is freed
  391. */
  392. GPtrArray *rspamd_glob_path (const gchar *dir,
  393. const gchar *pattern,
  394. gboolean recursive,
  395. GError **err);
  396. struct rspamd_counter_data {
  397. float mean;
  398. float stddev;
  399. guint64 number;
  400. };
  401. /**
  402. * Sets counter's data using exponential moving average
  403. * @param cd counter
  404. * @param value new counter value
  405. * @param alpha decay coefficient (0..1)
  406. * @return new counter value
  407. */
  408. float rspamd_set_counter_ema (struct rspamd_counter_data *cd,
  409. float value,
  410. float alpha);
  411. /**
  412. * Sets counter's data using flat moving average
  413. * @param cd counter
  414. * @param value new counter value
  415. * @return new counter value
  416. */
  417. double rspamd_set_counter (struct rspamd_counter_data *cd,
  418. gdouble value);
  419. /**
  420. * Shuffle elements in an array inplace
  421. * @param ar
  422. */
  423. void rspamd_ptr_array_shuffle (GPtrArray *ar);
  424. enum rspamd_pbkdf_version_id {
  425. RSPAMD_PBKDF_ID_V1 = 1,
  426. RSPAMD_PBKDF_ID_V2 = 2,
  427. RSPAMD_PBKDF_ID_MAX
  428. };
  429. struct rspamd_controller_pbkdf {
  430. const char *name;
  431. const char *alias;
  432. const char *description;
  433. int type; /* enum rspamd_cryptobox_pbkdf_type */
  434. gint id;
  435. guint complexity;
  436. gsize salt_len;
  437. gsize key_len;
  438. };
  439. extern const struct rspamd_controller_pbkdf pbkdf_list[];
  440. #ifdef __cplusplus
  441. }
  442. #endif
  443. #endif