aboutsummaryrefslogtreecommitdiffstats
path: root/src/libutil/util.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil/util.h')
-rw-r--r--src/libutil/util.h491
1 files changed, 491 insertions, 0 deletions
diff --git a/src/libutil/util.h b/src/libutil/util.h
new file mode 100644
index 000000000..0605fe87d
--- /dev/null
+++ b/src/libutil/util.h
@@ -0,0 +1,491 @@
+#ifndef RSPAMD_UTIL_H
+#define RSPAMD_UTIL_H
+
+#include "config.h"
+#include "mem_pool.h"
+#include "radix.h"
+#include "statfile.h"
+#include "printf.h"
+#include "fstring.h"
+#include "ucl.h"
+
+struct config_file;
+struct rspamd_main;
+struct workq;
+struct statfile;
+struct classifier_config;
+
+/**
+ * Union that is used for storing sockaddrs
+ */
+union sa_union {
+ struct sockaddr_storage ss;
+ struct sockaddr sa;
+ struct sockaddr_in s4;
+ struct sockaddr_in6 s6;
+ struct sockaddr_un su;
+};
+
+typedef struct _rspamd_inet_addr_s {
+ union sa_union addr;
+ socklen_t slen;
+ int af;
+} rspamd_inet_addr_t;
+
+
+/*
+ * Create socket and bind or connect it to specified address and port
+ */
+gint make_tcp_socket (struct addrinfo *, gboolean is_server, gboolean async);
+/*
+ * Create socket and bind or connect it to specified address and port
+ */
+gint make_udp_socket (struct addrinfo *, gboolean is_server, gboolean async);
+
+/*
+ * Create and bind or connect unix socket
+ */
+gint make_unix_socket (const gchar *, struct sockaddr_un *, gint type, gboolean is_server, gboolean async);
+
+/**
+ * Make a universal socket
+ * @param credits host, ip or path to unix socket
+ * @param port port (used for network sockets)
+ * @param type type of socket (SO_STREAM or SO_DGRAM)
+ * @param async make this socket asynced
+ * @param is_server make this socket as server socket
+ * @param try_resolve try name resolution for a socket (BLOCKING)
+ */
+gint make_universal_socket (const gchar *credits, guint16 port, gint type,
+ gboolean async, gboolean is_server, gboolean try_resolve);
+
+/**
+ * Make a universal sockets
+ * @param credits host, ip or path to unix socket (several items may be separated by ',')
+ * @param port port (used for network sockets)
+ * @param type type of socket (SO_STREAM or SO_DGRAM)
+ * @param async make this socket asynced
+ * @param is_server make this socket as server socket
+ * @param try_resolve try name resolution for a socket (BLOCKING)
+ */
+GList* make_universal_sockets_list (const gchar *credits, guint16 port, gint type,
+ gboolean async, gboolean is_server, gboolean try_resolve);
+/*
+ * Create socketpair
+ */
+gint make_socketpair (gint pair[2]);
+
+/*
+ * Write pid to file
+ */
+gint write_pid (struct rspamd_main *);
+
+/*
+ * Make specified socket non-blocking
+ */
+gint make_socket_nonblocking (gint);
+/*
+ * Make specified socket blocking
+ */
+gint make_socket_blocking (gint);
+
+/*
+ * Poll a sync socket for specified events
+ */
+gint poll_sync_socket (gint fd, gint timeout, short events);
+
+/*
+ * Init signals
+ */
+#ifdef HAVE_SA_SIGINFO
+void init_signals (struct sigaction *sa, void (*sig_handler)(gint, siginfo_t *, void *));
+#else
+void init_signals (struct sigaction *sa, void (*sig_handler)(gint));
+#endif
+
+/*
+ * Send specified signal to each worker
+ */
+void pass_signal_worker (GHashTable *, gint );
+/*
+ * Convert string to lowercase
+ */
+void convert_to_lowercase (gchar *str, guint size);
+
+#ifndef HAVE_SETPROCTITLE
+/*
+ * Process title utility functions
+ */
+gint init_title(gint argc, gchar *argv[], gchar *envp[]);
+gint setproctitle(const gchar *fmt, ...);
+#endif
+
+#ifndef HAVE_PIDFILE
+/*
+ * Pidfile functions from FreeBSD libutil code
+ */
+typedef struct rspamd_pidfh_s {
+ gint pf_fd;
+#ifdef HAVE_PATH_MAX
+ gchar pf_path[PATH_MAX + 1];
+#elif defined(HAVE_MAXPATHLEN)
+ gchar pf_path[MAXPATHLEN + 1];
+#else
+ gchar pf_path[1024 + 1];
+#endif
+ dev_t pf_dev;
+ ino_t pf_ino;
+} rspamd_pidfh_t;
+rspamd_pidfh_t *rspamd_pidfile_open(const gchar *path, mode_t mode, pid_t *pidptr);
+gint rspamd_pidfile_write(rspamd_pidfh_t *pfh);
+gint rspamd_pidfile_close(rspamd_pidfh_t *pfh);
+gint rspamd_pidfile_remove(rspamd_pidfh_t *pfh);
+#else
+typedef struct pidfh rspamd_pidfh_t;
+#define rspamd_pidfile_open pidfile_open
+#define rspamd_pidfile_write pidfile_write
+#define rspamd_pidfile_close pidfile_close
+#define rspamd_pidfile_remove pidfile_remove
+#endif
+
+/*
+ * Replace %r with rcpt value and %f with from value, new string is allocated in pool
+ */
+gchar* resolve_stat_filename (rspamd_mempool_t *pool, gchar *pattern, gchar *rcpt, gchar *from);
+#ifdef HAVE_CLOCK_GETTIME
+/*
+ * Calculate check time with specified resolution of timer
+ */
+const gchar* calculate_check_time (struct timeval *tv, struct timespec *begin, gint resolution, guint32 *scan_ms);
+#else
+const gchar* calculate_check_time (struct timeval *begin, gint resolution, guint32 *scan_ms);
+#endif
+
+/*
+ * File locking functions
+ */
+gboolean lock_file (gint fd, gboolean async);
+gboolean unlock_file (gint fd, gboolean async);
+
+/*
+ * Hash table utility functions for case insensitive hashing
+ */
+guint rspamd_strcase_hash (gconstpointer key);
+gboolean rspamd_strcase_equal (gconstpointer v, gconstpointer v2);
+
+/*
+ * Hash table utility functions for case sensitive hashing
+ */
+guint rspamd_str_hash (gconstpointer key);
+gboolean rspamd_str_equal (gconstpointer v, gconstpointer v2);
+
+
+/*
+ * Hash table utility functions for hashing fixed strings
+ */
+guint fstr_strcase_hash (gconstpointer key);
+gboolean fstr_strcase_equal (gconstpointer v, gconstpointer v2);
+
+/*
+ * Google perf-tools initialization function
+ */
+void gperf_profiler_init (struct config_file *cfg, const gchar *descr);
+
+/*
+ * Workarounds for older versions of glib
+ */
+#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 22))
+void g_ptr_array_unref (GPtrArray *array);
+#endif
+#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 14))
+void g_queue_clear (GQueue *queue);
+#endif
+
+
+/**
+ * Copy src to dest limited to len, in compare with standart strlcpy(3) rspamd strlcpy does not
+ * traverse the whole string and it is possible to use it for non NULL terminated strings. This is
+ * more like memccpy(dst, src, size, '\0')
+ *
+ * @param dst destination string
+ * @param src source string
+ * @param siz length of destination buffer
+ * @return bytes copied
+ */
+gsize rspamd_strlcpy (gchar *dst, const gchar *src, gsize siz);
+
+/**
+ * Lowercase strlcpy variant
+ * @param dst
+ * @param src
+ * @param siz
+ * @return
+ */
+gsize rspamd_strlcpy_tolower (gchar *dst, const gchar *src, gsize siz);
+
+/*
+ * Convert milliseconds to timeval fields
+ */
+#define msec_to_tv(msec, tv) do { (tv)->tv_sec = (msec) / 1000; (tv)->tv_usec = ((msec) - (tv)->tv_sec * 1000) * 1000; } while(0)
+#define double_to_tv(dbl, tv) do { (tv)->tv_sec = (int)(dbl); (tv)->tv_usec = ((dbl) - (int)(dbl))*1000*1000; } while(0)
+#define tv_to_msec(tv) (tv)->tv_sec * 1000 + (tv)->tv_usec / 1000
+
+/* Compare two emails for building emails tree */
+gint compare_email_func (gconstpointer a, gconstpointer b);
+
+/* Compare two urls for building emails tree */
+gint compare_url_func (gconstpointer a, gconstpointer b);
+
+/*
+ * Find string find in string s ignoring case
+ */
+gchar* rspamd_strncasestr (const gchar *s, const gchar *find, gint len);
+
+/*
+ * Try to convert string of length to long
+ */
+gboolean rspamd_strtol (const gchar *s, gsize len, glong *value);
+
+/*
+ * Try to convert string of length to unsigned long
+ */
+gboolean rspamd_strtoul (const gchar *s, gsize len, gulong *value);
+
+/**
+ * Try to allocate a file on filesystem (using fallocate or posix_fallocate)
+ * @param fd descriptor
+ * @param offset offset of file
+ * @param len length to allocate
+ * @return -1 in case of failure
+ */
+gint rspamd_fallocate (gint fd, off_t offset, off_t len);
+
+/**
+ * Return worker's control structure by its type
+ * @param type
+ * @return worker's control structure or NULL
+ */
+extern worker_t* get_worker_by_type (GQuark type);
+
+/**
+ * Utils for working with threads to be compatible with all glib versions
+ */
+typedef struct rspamd_mutex_s {
+#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
+ GMutex mtx;
+#else
+ GStaticMutex mtx;
+#endif
+} rspamd_mutex_t;
+
+typedef struct rspamd_rwlock_s {
+#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
+ GRWLock rwlock;
+#else
+ GStaticRWLock rwlock;
+#endif
+} rspamd_rwlock_t;
+
+
+/**
+ * Create new mutex
+ * @return mutex or NULL
+ */
+rspamd_mutex_t* rspamd_mutex_new (void);
+
+/**
+ * Lock mutex
+ * @param mtx
+ */
+void rspamd_mutex_lock (rspamd_mutex_t *mtx);
+
+/**
+ * Unlock mutex
+ * @param mtx
+ */
+void rspamd_mutex_unlock (rspamd_mutex_t *mtx);
+
+/**
+ * Clear rspamd mutex
+ * @param mtx
+ */
+void rspamd_mutex_free (rspamd_mutex_t *mtx);
+
+/**
+ * Create new rwloc
+ * @return
+ */
+rspamd_rwlock_t* rspamd_rwlock_new (void);
+
+/**
+ * Lock rwlock for writing
+ * @param mtx
+ */
+void rspamd_rwlock_writer_lock (rspamd_rwlock_t *mtx);
+
+/**
+ * Lock rwlock for reading
+ * @param mtx
+ */
+void rspamd_rwlock_reader_lock (rspamd_rwlock_t *mtx);
+
+/**
+ * Unlock rwlock from writing
+ * @param mtx
+ */
+void rspamd_rwlock_writer_unlock (rspamd_rwlock_t *mtx);
+
+/**
+ * Unlock rwlock from reading
+ * @param mtx
+ */
+void rspamd_rwlock_reader_unlock (rspamd_rwlock_t *mtx);
+
+/**
+ * Free rwlock
+ * @param mtx
+ */
+void rspamd_rwlock_free (rspamd_rwlock_t *mtx);
+
+static inline void
+rspamd_cond_wait (GCond *cond, rspamd_mutex_t *mtx)
+{
+#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
+ g_cond_wait (cond, &mtx->mtx);
+#else
+ g_cond_wait (cond, g_static_mutex_get_mutex (&mtx->mtx));
+#endif
+}
+
+/**
+ * Create new named thread
+ * @param name name pattern
+ * @param func function to start
+ * @param data data to pass to function
+ * @param err error pointer
+ * @return new thread object that can be joined
+ */
+GThread* rspamd_create_thread (const gchar *name, GThreadFunc func, gpointer data, GError **err);
+
+/**
+ * Return 32bit murmur hash value for specified input
+ * @param in input data
+ * @param len length of the input data
+ * @code
+ * MurmurHash3 was created by Austin Appleby in 2008. The cannonical
+ * implementations are in C++ and placed in the public.
+ *
+ * https://sites.google.com/site/murmurhash/
+ *
+ * Seungyoung Kim has ported it's cannonical implementation to C language
+ * in 2012 and published it as a part of qLibc component.
+ * @endcode
+ * @return
+ */
+guint32 murmur32_hash (const guint8 *in, gsize len);
+
+/**
+ * Return 32bit murmur hash value for specified input
+ * @param in input data
+ * @param len length of the input data
+ * @param out array of 2 guint64 variables
+ * @code
+ * MurmurHash3 was created by Austin Appleby in 2008. The cannonical
+ * implementations are in C++ and placed in the public.
+ *
+ * https://sites.google.com/site/murmurhash/
+ *
+ * Seungyoung Kim has ported it's cannonical implementation to C language
+ * in 2012 and published it as a part of qLibc component.
+ * @endcode
+ * @return
+ */
+void murmur128_hash (const guint8 *in, gsize len, guint64 out[]);
+
+/**
+ * Deep copy of one hash table to another
+ * @param src source hash
+ * @param dst destination hash
+ * @param key_copy_func function called to copy or modify keys (or NULL)
+ * @param value_copy_func function called to copy or modify values (or NULL)
+ * @param ud user data for copy functions
+ */
+void rspamd_hash_table_copy (GHashTable *src, GHashTable *dst,
+ gpointer (*key_copy_func)(gconstpointer data, gpointer ud),
+ gpointer (*value_copy_func)(gconstpointer data, gpointer ud),
+ gpointer ud);
+
+/**
+ * Utility function to provide mem_pool copy for rspamd_hash_table_copy function
+ * @param data string to copy
+ * @param ud memory pool to use
+ * @return
+ */
+gpointer rspamd_str_pool_copy (gconstpointer data, gpointer ud);
+
+/**
+ * Parse ipv4 address with optional mask in CIDR format
+ * @param line cidr notation of ipv4 address
+ * @param ina destination address
+ * @param mask destination mask
+ * @return
+ */
+gboolean parse_ipmask_v4 (const char *line, struct in_addr *ina, int *mask);
+
+/**
+ * Read passphrase from tty
+ * @param buf buffer to fill with a password
+ * @param size size of the buffer
+ * @param rwflag unused flag
+ * @param key unused key
+ * @return size of password read
+ */
+gint rspamd_read_passphrase (gchar *buf, gint size, gint rwflag, gpointer key);
+
+/**
+ * Check whether specified ip is valid (not INADDR_ANY or INADDR_NONE) for ipv4 or ipv6
+ * @param ptr pointer to struct in_addr or struct in6_addr
+ * @param af address family (AF_INET or AF_INET6)
+ * @return TRUE if the address is valid
+ */
+gboolean rspamd_ip_is_valid (rspamd_inet_addr_t *addr);
+
+/**
+ * Emit UCL object to gstring
+ * @param obj object to emit
+ * @param emit_type emitter type
+ * @param target target string
+ */
+void rspamd_ucl_emit_gstring (ucl_object_t *obj, enum ucl_emitter emit_type, GString *target);
+
+/**
+ * Accept from listening socket filling addr structure
+ * @param sock listening socket
+ * @param addr
+ * @return
+ */
+gint rspamd_accept_from_socket (gint sock, rspamd_inet_addr_t *addr);
+
+/**
+ * Try to parse address from string
+ * @param target target to fill
+ * @param src IP string representation
+ * @return TRUE if addr has been parsed
+ */
+gboolean rspamd_parse_inet_address (rspamd_inet_addr_t *target, const char *src);
+
+/**
+ * Returns string representation of inet address
+ * @param addr
+ * @return statically allocated string pointer (not thread safe)
+ */
+const char* rspamd_inet_address_to_string (rspamd_inet_addr_t *addr);
+
+/**
+ * Returns port number for the specified inet address in host byte order
+ * @param addr
+ * @return
+ */
+uint16_t rspamd_inet_address_get_port (rspamd_inet_addr_t *addr);
+
+#endif