diff options
Diffstat (limited to 'src/libutil/util.h')
-rw-r--r-- | src/libutil/util.h | 491 |
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 |