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 12KB

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