diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2014-10-28 13:36:15 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2014-10-28 13:36:15 +0000 |
commit | b4ce748572e3097982b951fac69c0e65db8b4118 (patch) | |
tree | 3e372ff1f7e9d2ef5e4b7a33e12e34b31e95f1a5 | |
parent | d95807104076189411987dcc733a23a94b8812a5 (diff) | |
download | rspamd-b4ce748572e3097982b951fac69c0e65db8b4118.tar.gz rspamd-b4ce748572e3097982b951fac69c0e65db8b4118.zip |
Split addr definition from the utils code.
-rw-r--r-- | src/libutil/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/libutil/addr.c | 184 | ||||
-rw-r--r-- | src/libutil/addr.h | 98 | ||||
-rw-r--r-- | src/libutil/util.c | 159 | ||||
-rw-r--r-- | src/libutil/util.h | 79 |
5 files changed, 295 insertions, 229 deletions
diff --git a/src/libutil/CMakeLists.txt b/src/libutil/CMakeLists.txt index 7a8b3add5..01c88769b 100644 --- a/src/libutil/CMakeLists.txt +++ b/src/libutil/CMakeLists.txt @@ -1,5 +1,7 @@ # Librspamd-util -SET(LIBRSPAMDUTILSRC aio_event.c +SET(LIBRSPAMDUTILSRC + addr.c + aio_event.c bloom.c diff.c fstring.c diff --git a/src/libutil/addr.c b/src/libutil/addr.c new file mode 100644 index 000000000..a06dc2662 --- /dev/null +++ b/src/libutil/addr.c @@ -0,0 +1,184 @@ +/* Copyright (c) 2014, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "addr.h" +#include "util.h" +#include "logger.h" + +gboolean +rspamd_ip_is_valid (rspamd_inet_addr_t *addr) +{ + const struct in_addr ip4_any = { INADDR_ANY }, ip4_none = { INADDR_NONE }; + const struct in6_addr ip6_any = IN6ADDR_ANY_INIT; + + gboolean ret = FALSE; + + if (G_LIKELY (addr->af == AF_INET)) { + if (memcmp (&addr->addr.s4.sin_addr, &ip4_any, + sizeof (struct in_addr)) != 0 && + memcmp (&addr->addr.s4.sin_addr, &ip4_none, + sizeof (struct in_addr)) != 0) { + ret = TRUE; + } + } + else if (G_UNLIKELY (addr->af == AF_INET6)) { + if (memcmp (&addr->addr.s6.sin6_addr, &ip6_any, + sizeof (struct in6_addr)) != 0) { + ret = TRUE; + } + } + + return ret; +} + +gint +rspamd_accept_from_socket (gint sock, rspamd_inet_addr_t *addr) +{ + gint nfd, serrno; + socklen_t len = sizeof (addr->addr.ss); + + if ((nfd = accept (sock, &addr->addr.sa, &len)) == -1) { + if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) { + return 0; + } + return -1; + } + + addr->slen = len; + addr->af = addr->addr.sa.sa_family; + + if (make_socket_nonblocking (nfd) < 0) { + goto out; + } + + /* Set close on exec */ + if (fcntl (nfd, F_SETFD, FD_CLOEXEC) == -1) { + msg_warn ("fcntl failed: %d, '%s'", errno, strerror (errno)); + goto out; + } + + return (nfd); + +out: + serrno = errno; + close (nfd); + errno = serrno; + return (-1); + +} + +gboolean +rspamd_parse_inet_address (rspamd_inet_addr_t *target, const char *src) +{ + gboolean ret = FALSE; + + if (inet_pton (AF_INET6, src, &target->addr.s6.sin6_addr) == 1) { + target->af = AF_INET6; + target->slen = sizeof (target->addr.s6); + ret = TRUE; + } + else if (inet_pton (AF_INET, src, &target->addr.s4.sin_addr) == 1) { + target->af = AF_INET; + target->slen = sizeof (target->addr.s4); + ret = TRUE; + } + + target->addr.sa.sa_family = target->af; + + return ret; +} + +const char * +rspamd_inet_address_to_string (rspamd_inet_addr_t *addr) +{ + static char addr_str[INET6_ADDRSTRLEN + 1]; + + switch (addr->af) { + case AF_INET: + return inet_ntop (addr->af, &addr->addr.s4.sin_addr, addr_str, + sizeof (addr_str)); + case AF_INET6: + return inet_ntop (addr->af, &addr->addr.s6.sin6_addr, addr_str, + sizeof (addr_str)); + case AF_UNIX: + return addr->addr.su.sun_path; + } + + return "undefined"; +} + +uint16_t +rspamd_inet_address_get_port (rspamd_inet_addr_t *addr) +{ + switch (addr->af) { + case AF_INET: + return ntohs (addr->addr.s4.sin_port); + case AF_INET6: + return ntohs (addr->addr.s6.sin6_port); + } + + return 0; +} + +void +rspamd_inet_address_set_port (rspamd_inet_addr_t *addr, uint16_t port) +{ + switch (addr->af) { + case AF_INET: + addr->addr.s4.sin_port = htons (port); + break; + case AF_INET6: + addr->addr.s6.sin6_port = htons (port); + break; + } +} + +int +rspamd_inet_address_connect (rspamd_inet_addr_t *addr, gint type, + gboolean async) +{ + int fd, r; + + if (addr == NULL) { + return -1; + } + + fd = rspamd_socket_create (addr->af, type, 0, async); + if (fd == -1) { + return -1; + } + + r = connect (fd, &addr->addr.sa, addr->slen); + + if (r == -1) { + if (!async || errno != EINPROGRESS) { + close (fd); + msg_warn ("connect failed: %d, '%s'", errno, + strerror (errno)); + return -1; + } + } + + return fd; +} diff --git a/src/libutil/addr.h b/src/libutil/addr.h new file mode 100644 index 000000000..049cc88c3 --- /dev/null +++ b/src/libutil/addr.h @@ -0,0 +1,98 @@ +/* Copyright (c) 2014, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef ADDR_H_ +#define ADDR_H_ + +#include "config.h" + +/** + * 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; + +/** + * 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); + +/** + * Set port for inet address + */ +void rspamd_inet_address_set_port (rspamd_inet_addr_t *addr, uint16_t port); + +/** + * Connect to inet_addr address + * @param addr + * @param async perform operations asynchronously + * @return newly created and connected socket + */ +int rspamd_inet_address_connect (rspamd_inet_addr_t *addr, gint type, + gboolean async); + +/** + * 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); + +/** + * 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); + +#endif /* ADDR_H_ */ diff --git a/src/libutil/util.c b/src/libutil/util.c index 73ab64453..ec125704f 100644 --- a/src/libutil/util.c +++ b/src/libutil/util.c @@ -98,7 +98,7 @@ poll_sync_socket (gint fd, gint timeout, short events) return r; } -static gint +gint rspamd_socket_create (gint af, gint type, gint protocol, gboolean async) { gint fd; @@ -1973,32 +1973,6 @@ restart: #endif } -gboolean -rspamd_ip_is_valid (rspamd_inet_addr_t *addr) -{ - const struct in_addr ip4_any = { INADDR_ANY }, ip4_none = { INADDR_NONE }; - const struct in6_addr ip6_any = IN6ADDR_ANY_INIT; - - gboolean ret = FALSE; - - if (G_LIKELY (addr->af == AF_INET)) { - if (memcmp (&addr->addr.s4.sin_addr, &ip4_any, - sizeof (struct in_addr)) != 0 && - memcmp (&addr->addr.s4.sin_addr, &ip4_none, - sizeof (struct in_addr)) != 0) { - ret = TRUE; - } - } - else if (G_UNLIKELY (addr->af == AF_INET6)) { - if (memcmp (&addr->addr.s6.sin6_addr, &ip6_any, - sizeof (struct in6_addr)) != 0) { - ret = TRUE; - } - } - - return ret; -} - /* * GString ucl emitting functions */ @@ -2079,137 +2053,6 @@ rspamd_ucl_emit_gstring (ucl_object_t *obj, ucl_object_emit_full (obj, emit_type, &func); } -gint -rspamd_accept_from_socket (gint sock, rspamd_inet_addr_t *addr) -{ - gint nfd, serrno; - socklen_t len = sizeof (addr->addr.ss); - - if ((nfd = accept (sock, &addr->addr.sa, &len)) == -1) { - if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) { - return 0; - } - return -1; - } - - addr->slen = len; - addr->af = addr->addr.sa.sa_family; - - if (make_socket_nonblocking (nfd) < 0) { - goto out; - } - - /* Set close on exec */ - if (fcntl (nfd, F_SETFD, FD_CLOEXEC) == -1) { - msg_warn ("fcntl failed: %d, '%s'", errno, strerror (errno)); - goto out; - } - - return (nfd); - -out: - serrno = errno; - close (nfd); - errno = serrno; - return (-1); - -} - -gboolean -rspamd_parse_inet_address (rspamd_inet_addr_t *target, const char *src) -{ - gboolean ret = FALSE; - - if (inet_pton (AF_INET6, src, &target->addr.s6.sin6_addr) == 1) { - target->af = AF_INET6; - target->slen = sizeof (target->addr.s6); - ret = TRUE; - } - else if (inet_pton (AF_INET, src, &target->addr.s4.sin_addr) == 1) { - target->af = AF_INET; - target->slen = sizeof (target->addr.s4); - ret = TRUE; - } - - target->addr.sa.sa_family = target->af; - - return ret; -} - -const char * -rspamd_inet_address_to_string (rspamd_inet_addr_t *addr) -{ - static char addr_str[INET6_ADDRSTRLEN + 1]; - - switch (addr->af) { - case AF_INET: - return inet_ntop (addr->af, &addr->addr.s4.sin_addr, addr_str, - sizeof (addr_str)); - case AF_INET6: - return inet_ntop (addr->af, &addr->addr.s6.sin6_addr, addr_str, - sizeof (addr_str)); - case AF_UNIX: - return addr->addr.su.sun_path; - } - - return "undefined"; -} - -uint16_t -rspamd_inet_address_get_port (rspamd_inet_addr_t *addr) -{ - switch (addr->af) { - case AF_INET: - return ntohs (addr->addr.s4.sin_port); - case AF_INET6: - return ntohs (addr->addr.s6.sin6_port); - } - - return 0; -} - -void -rspamd_inet_address_set_port (rspamd_inet_addr_t *addr, uint16_t port) -{ - switch (addr->af) { - case AF_INET: - addr->addr.s4.sin_port = htons (port); - break; - case AF_INET6: - addr->addr.s6.sin6_port = htons (port); - break; - } -} - -int -rspamd_inet_address_connect (rspamd_inet_addr_t *addr, gint type, - gboolean async) -{ - int fd, r; - - if (addr == NULL) { - return -1; - } - - fd = rspamd_socket_create (addr->af, type, 0, async); - if (fd == -1) { - return -1; - } - - r = connect (fd, &addr->addr.sa, addr->slen); - - if (r == -1) { - if (!async || errno != EINPROGRESS) { - close (fd); - msg_warn ("connect failed: %d, '%s'", errno, - strerror (errno)); - return -1; - } - } - - return fd; -} - /* * We use here z-base32 encoding described here: * http://philzimmermann.com/docs/human-oriented-base-32-encoding.txt diff --git a/src/libutil/util.h b/src/libutil/util.h index 40d8004e3..ed4e6fcca 100644 --- a/src/libutil/util.h +++ b/src/libutil/util.h @@ -7,6 +7,7 @@ #include "printf.h" #include "fstring.h" #include "ucl.h" +#include "addr.h" struct rspamd_config; struct rspamd_main; @@ -15,23 +16,14 @@ struct rspamd_statfile_config; struct rspamd_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 generic socket + * @param af address family + * @param type socket type + * @param protocol socket protocol + * @param async set non-blocking on a socket + * @return socket FD or -1 in case of error + */ +gint rspamd_socket_create (gint af, gint type, gint protocol, gboolean async); /* * Create socket and bind or connect it to specified address and port */ @@ -418,14 +410,6 @@ gpointer rspamd_str_pool_copy (gconstpointer data, gpointer ud); 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 @@ -436,51 +420,6 @@ void rspamd_ucl_emit_gstring (ucl_object_t *obj, 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); - -/** - * Set port for inet address - */ -void rspamd_inet_address_set_port (rspamd_inet_addr_t *addr, uint16_t port); - -/** - * Connect to inet_addr address - * @param addr - * @param async perform operations asynchronously - * @return newly created and connected socket - */ -int rspamd_inet_address_connect (rspamd_inet_addr_t *addr, gint type, - gboolean async); - -/** * Encode string using base32 encoding * @param in input * @param inlen input length |