Browse Source

Rework inet_address structure.

- Now addresses are opaque.
- Save memory by splitting unix and inet sockaddrs.
- Rework all functions related to inet addrs.
- Use ptr arrays instead of home-made static arrays.
tags/0.9.0
Vsevolod Stakhov 9 years ago
parent
commit
a943f89d45
2 changed files with 444 additions and 127 deletions
  1. 374
    97
      src/libutil/addr.c
  2. 70
    30
      src/libutil/addr.h

+ 374
- 97
src/libutil/addr.c View File

@@ -32,25 +32,100 @@ enum {
RSPAMD_IPV6_UNSUPPORTED
} ipv6_status = RSPAMD_IPV6_UNDEFINED;

/**
* Union that is used for storing sockaddrs
*/
union sa_union {
struct sockaddr sa;
struct sockaddr_in s4;
struct sockaddr_in6 s6;
struct sockaddr_un su;
struct sockaddr_storage ss;
};

union sa_inet {
struct sockaddr sa;
struct sockaddr_in s4;
struct sockaddr_in6 s6;
};

struct rspamd_addr_unix {
struct sockaddr_un addr;
gint mode;
uid_t owner;
gid_t group;
};

struct rspamd_addr_inet {
union sa_inet addr;
};

struct rspamd_inet_addr_s {
union {
struct rspamd_addr_inet in;
struct rspamd_addr_unix *un;
} u;
gint af;
socklen_t slen;
};

static void
rspamd_ip_validate_af (rspamd_inet_addr_t *addr)
{
if (addr->addr.sa.sa_family != addr->af) {
addr->addr.sa.sa_family = addr->af;
if (addr->af != AF_UNIX) {
if (addr->u.in.addr.sa.sa_family != addr->af) {
addr->u.in.addr.sa.sa_family = addr->af;
}
}

if (addr->af == AF_INET) {
addr->slen = sizeof (addr->addr.s4);
addr->slen = sizeof (struct sockaddr_in);
}
else if (addr->af == AF_INET6) {
addr->slen = sizeof (addr->addr.s6);
addr->slen = sizeof (struct sockaddr_in6);
}
else if (addr->af == AF_UNIX) {
#ifdef SUN_LEN
addr->slen = SUN_LEN (&addr->addr.su);
addr->slen = SUN_LEN (&addr->u.un->addr);
#else
addr->slen = sizeof (addr->addr.su);
addr->slen = sizeof (addr->u.un->addr);
#endif
#if defined(FREEBSD) || defined(__APPLE__)
addr->u.un->addr.sun_len = addr->slen;
#endif
}
}


static rspamd_inet_addr_t *
rspamd_inet_addr_create (gint af)
{
rspamd_inet_addr_t *addr;

addr = g_slice_alloc (sizeof (rspamd_inet_addr_t));

if (af == AF_UNIX) {
addr->u.un = g_slice_alloc (sizeof (*addr->u.un));
addr->slen = sizeof (addr->u.un->addr);
}

addr->af = af;

rspamd_ip_validate_af (addr);

return addr;
}

void
rspamd_inet_address_destroy (rspamd_inet_addr_t *addr)
{
if (addr) {
if (addr->af == AF_UNIX) {
if (addr->u.un) {
g_slice_free1 (sizeof (*addr->u.un), addr->u.un);
}
}
g_slice_free1 (sizeof (rspamd_inet_addr_t), addr);
}
}

@@ -90,22 +165,22 @@ rspamd_ip_check_ipv6 (void)
}

gboolean
rspamd_ip_is_valid (rspamd_inet_addr_t *addr)
rspamd_ip_is_valid (const 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,
if (memcmp (&addr->u.in.addr.s4.sin_addr, &ip4_any,
sizeof (struct in_addr)) != 0 &&
memcmp (&addr->addr.s4.sin_addr, &ip4_none,
memcmp (&addr->u.in.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,
if (memcmp (&addr->u.in.addr.s6.sin6_addr, &ip6_any,
sizeof (struct in6_addr)) != 0) {
ret = TRUE;
}
@@ -115,20 +190,34 @@ rspamd_ip_is_valid (rspamd_inet_addr_t *addr)
}

gint
rspamd_accept_from_socket (gint sock, rspamd_inet_addr_t *addr)
rspamd_accept_from_socket (gint sock, rspamd_inet_addr_t **target)
{
gint nfd, serrno;
socklen_t len = sizeof (addr->addr.ss);
union sa_union su;
socklen_t len = sizeof (su);
rspamd_inet_addr_t *addr = NULL;

if ((nfd = accept (sock, &su.sa, &len)) == -1) {
if (target) {
*target = NULL;
}

if ((nfd = accept (sock, &addr->addr.sa, &len)) == -1) {
if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) {
return 0;
}
return -1;
}

addr = rspamd_inet_addr_create (su.sa.sa_family);
addr->slen = len;
addr->af = addr->addr.sa.sa_family;

if (addr->af == AF_UNIX) {
addr->u.un = g_slice_alloc (sizeof (*addr->u.un));
memcpy (&addr->u.un->addr, &su.su, sizeof (struct sockaddr_un));
}
else {
memcpy (&addr->u.in.addr, &su, MIN (len, sizeof (addr->u.in.addr)));
}

if (rspamd_socket_nonblocking (nfd) < 0) {
goto out;
@@ -140,37 +229,48 @@ rspamd_accept_from_socket (gint sock, rspamd_inet_addr_t *addr)
goto out;
}

if (target) {
*target = addr;
}
else {
/* Avoid leak */
rspamd_inet_address_destroy (addr);
}

return (nfd);

out:
serrno = errno;
close (nfd);
errno = serrno;
rspamd_inet_address_destroy (addr);

return (-1);

}

static gboolean
rspamd_parse_unix_path (rspamd_inet_addr_t *target, const char *src)
rspamd_parse_unix_path (rspamd_inet_addr_t **target, const char *src)
{
gchar **tokens, **cur_tok, *p, *pwbuf;
gint pwlen;
struct passwd pw, *ppw;
struct group gr, *pgr;
rspamd_inet_addr_t *addr;

tokens = g_strsplit_set (src, " ", -1);

target->af = AF_UNIX;
target->slen = sizeof (target->addr.su);
rspamd_strlcpy (target->addr.su.sun_path, tokens[0],
sizeof (target->addr.su.sun_path));
#ifdef FREEBSD
target->addr.su.sun_len = SUN_LEN (&target->addr.su);
addr = rspamd_inet_addr_create (AF_UNIX);
rspamd_strlcpy (addr->u.un->addr.sun_path, tokens[0],
sizeof (addr->u.un->addr.sun_path));
#if defined(FREEBSD) || defined(__APPLE__)
addr->u.un->addr.sun_len = SUN_LEN (&addr->u.un->addr);
#endif

target->mode = 00644;
target->owner = 0;
target->group = 0;
addr->u.un->mode = 00644;
addr->u.un->mode = 0;
addr->u.un->group = 0;

cur_tok = &tokens[1];
pwlen = sysconf (_SC_GETPW_R_SIZE_MAX);
@@ -181,12 +281,12 @@ rspamd_parse_unix_path (rspamd_inet_addr_t *target, const char *src)
if (g_ascii_strncasecmp (*cur_tok, "mode=", sizeof ("mode=") - 1) == 0) {
p = strchr (*cur_tok, '=');
/* XXX: add error check */
target->mode = strtoul (p + 1, NULL, 0);
addr->u.un->mode = strtoul (p + 1, NULL, 0);

if (target->mode == 0) {
if (addr->u.un->mode == 0) {
msg_err ("bad mode: %s", p + 1);
errno = EINVAL;
return FALSE;
goto err;
}
}
else if (g_ascii_strncasecmp (*cur_tok, "owner=",
@@ -198,10 +298,10 @@ rspamd_parse_unix_path (rspamd_inet_addr_t *target, const char *src)
if (ppw == NULL) {
errno = ENOENT;
}
return FALSE;
goto err;
}
target->owner = pw.pw_uid;
target->group = pw.pw_gid;
addr->u.un->owner = pw.pw_uid;
addr->u.un->group = pw.pw_gid;
}
else if (g_ascii_strncasecmp (*cur_tok, "group=",
sizeof ("group=") - 1) == 0) {
@@ -212,20 +312,37 @@ rspamd_parse_unix_path (rspamd_inet_addr_t *target, const char *src)
if (pgr == NULL) {
errno = ENOENT;
}
return FALSE;
goto err;
}
target->group = gr.gr_gid;
addr->u.un->group = gr.gr_gid;
}
cur_tok ++;
}

if (target) {
*target = addr;
}
else {
rspamd_inet_address_destroy (addr);
}

return TRUE;

err:

rspamd_inet_address_destroy (addr);
return FALSE;
}

gboolean
rspamd_parse_inet_address (rspamd_inet_addr_t *target, const char *src)
rspamd_parse_inet_address (rspamd_inet_addr_t **target, const char *src)
{
gboolean ret = FALSE;
rspamd_inet_addr_t *addr;
union sa_inet su;

g_assert (src != NULL);
g_assert (target != NULL);

rspamd_ip_check_ipv6 ();

@@ -233,49 +350,49 @@ rspamd_parse_inet_address (rspamd_inet_addr_t *target, const char *src)
return rspamd_parse_unix_path (target, src);
}
else if (ipv6_status == RSPAMD_IPV6_SUPPORTED &&
inet_pton (AF_INET6, src, &target->addr.s6.sin6_addr) == 1) {
target->af = AF_INET6;
target->slen = sizeof (target->addr.s6);
inet_pton (AF_INET6, src, &su.s6.sin6_addr) == 1) {
addr = rspamd_inet_addr_create (AF_INET6);
memcpy (&addr->u.in.addr.s6.sin6_addr, &su.s6.sin6_addr,
sizeof (struct in6_addr));
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);
else if (inet_pton (AF_INET, src, &su.s4.sin_addr) == 1) {
addr = rspamd_inet_addr_create (AF_INET6);
memcpy (&addr->u.in.addr.s4.sin_addr, &su.s4.sin_addr,
sizeof (struct in_addr));
ret = TRUE;
}

target->addr.sa.sa_family = target->af;

return ret;
}

const char *
rspamd_inet_address_to_string (rspamd_inet_addr_t *addr)
rspamd_inet_address_to_string (const 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,
return inet_ntop (addr->af, &addr->u.in.addr.s4.sin_addr, addr_str,
sizeof (addr_str));
case AF_INET6:
return inet_ntop (addr->af, &addr->addr.s6.sin6_addr, addr_str,
return inet_ntop (addr->af, &addr->u.in.addr.s6.sin6_addr, addr_str,
sizeof (addr_str));
case AF_UNIX:
return addr->addr.su.sun_path;
return addr->u.un->addr.sun_path;
}

return "undefined";
}

uint16_t
rspamd_inet_address_get_port (rspamd_inet_addr_t *addr)
rspamd_inet_address_get_port (const rspamd_inet_addr_t *addr)
{
switch (addr->af) {
case AF_INET:
return ntohs (addr->addr.s4.sin_port);
return ntohs (addr->u.in.addr.s4.sin_port);
case AF_INET6:
return ntohs (addr->addr.s6.sin6_port);
return ntohs (addr->u.in.addr.s6.sin6_port);
}

return 0;
@@ -286,32 +403,38 @@ 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);
addr->u.in.addr.s4.sin_port = htons (port);
break;
case AF_INET6:
addr->addr.s6.sin6_port = htons (port);
addr->u.in.addr.s6.sin6_port = htons (port);
break;
}
}

int
rspamd_inet_address_connect (rspamd_inet_addr_t *addr, gint type,
rspamd_inet_address_connect (const rspamd_inet_addr_t *addr, gint type,
gboolean async)
{
int fd, r;
const struct sockaddr *sa;

if (addr == NULL) {
return -1;
}

rspamd_ip_validate_af (addr);

fd = rspamd_socket_create (addr->af, type, 0, async);
if (fd == -1) {
return -1;
}

r = connect (fd, &addr->addr.sa, addr->slen);
if (addr->af == AF_UNIX) {
sa = (const struct sockaddr *)&addr->u.un->addr;
}
else {
sa = &addr->u.in.addr.sa;
}

r = connect (fd, sa, addr->slen);

if (r == -1) {
if (!async || errno != EINPROGRESS) {
@@ -326,29 +449,37 @@ rspamd_inet_address_connect (rspamd_inet_addr_t *addr, gint type,
}

int
rspamd_inet_address_listen (rspamd_inet_addr_t *addr, gint type,
rspamd_inet_address_listen (const rspamd_inet_addr_t *addr, gint type,
gboolean async)
{
gint fd, r;
gint on = 1;
const struct sockaddr *sa;
const char *path;

if (addr == NULL) {
return -1;
}

rspamd_ip_validate_af (addr);
fd = rspamd_socket_create (addr->af, type, 0, async);
if (fd == -1) {
return -1;
}

if (addr->af == AF_UNIX && access (addr->addr.su.sun_path, W_OK) != -1) {
if (addr->af == AF_UNIX && access (addr->u.un->addr.sun_path, W_OK) != -1) {
/* Unlink old socket */
(void)unlink (addr->addr.su.sun_path);
(void)unlink (addr->u.un->addr.sun_path);
}

if (addr->af == AF_UNIX) {
sa = (const struct sockaddr *)&addr->u.un->addr;
}
else {
sa = &addr->u.in.addr.sa;
}

setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof (gint));
r = bind (fd, &addr->addr.sa, addr->slen);
r = bind (fd, sa, addr->slen);
if (r == -1) {
if (!async || errno != EINPROGRESS) {
close (fd);
@@ -361,15 +492,16 @@ rspamd_inet_address_listen (rspamd_inet_addr_t *addr, gint type,
if (type != SOCK_DGRAM) {

if (addr->af == AF_UNIX) {
path = addr->u.un->addr.sun_path;
/* Try to set mode and owner */
if (chown (addr->addr.su.sun_path, addr->owner, addr->group) == -1) {
if (chown (path, addr->u.un->owner, addr->u.un->group) == -1) {
msg_info ("cannot change owner for %s to %d:%d: %s",
addr->addr.su.sun_path, addr->owner, addr->group,
path, addr->u.un->owner, addr->u.un->group,
strerror (errno));
}
if (chmod (addr->addr.su.sun_path, addr->mode) == -1) {
if (chmod (path, addr->u.un->mode) == -1) {
msg_info ("cannot change mode for %s to %od %s",
addr->addr.su.sun_path, addr->mode, strerror (errno));
path, addr->u.un->mode, strerror (errno));
}
}
r = listen (fd, -1);
@@ -384,10 +516,67 @@ rspamd_inet_address_listen (rspamd_inet_addr_t *addr, gint type,
return fd;
}

gssize
rspamd_inet_address_recvfrom (gint fd, void *buf, gsize len, gint fl,
rspamd_inet_addr_t **target)
{
gssize ret;
union sa_union su;
socklen_t slen = sizeof (su);
rspamd_inet_addr_t *addr = NULL;

if ((ret = recvfrom (fd, buf, len, fl, &su.sa, &slen)) == -1) {
if (target) {
*target = NULL;
}

return -1;
}

if (target) {
addr = rspamd_inet_addr_create (su.sa.sa_family);
addr->slen = len;

if (addr->af == AF_UNIX) {
addr->u.un = g_slice_alloc (sizeof (*addr->u.un));
memcpy (&addr->u.un->addr, &su.su, sizeof (struct sockaddr_un));
}
else {
memcpy (&addr->u.in.addr, &su, MIN (len, sizeof (addr->u.in.addr)));
}

*target = addr;
}

return (ret);
}

gssize
rspamd_inet_address_sendto (gint fd, const void *buf, gsize len, gint fl,
const rspamd_inet_addr_t *addr)
{
gssize r;
const struct sockaddr *sa;

if (addr == NULL) {
return -1;
}

if (addr->af == AF_UNIX) {
sa = (struct sockaddr *)&addr->u.un->addr;
}
else {
sa = &addr->u.in.addr.sa;
}

r = sendto (fd, buf, len, fl, sa, addr->slen);

return r;
}

gboolean
rspamd_parse_host_port_priority_strv (gchar **tokens,
rspamd_inet_addr_t **addr,
guint *max_addrs,
GPtrArray **addrs,
guint *priority,
gchar **name,
guint default_port,
@@ -476,34 +665,30 @@ rspamd_parse_host_port_priority_strv (gchar **tokens,
/* Now copy up to max_addrs of addresses */
addr_cnt = 0;
cur = res;
while (cur && addr_cnt < *max_addrs) {
while (cur) {
cur = cur->ai_next;
addr_cnt ++;
}

if (pool == NULL) {
*addr = g_new (rspamd_inet_addr_t, addr_cnt);
}
else {
*addr = rspamd_mempool_alloc (pool, addr_cnt *
sizeof (rspamd_inet_addr_t));
*addrs = g_ptr_array_new_full (addr_cnt,
(GDestroyNotify)rspamd_inet_address_destroy);
if (pool != NULL) {
rspamd_mempool_add_destructor (pool,
rspamd_ptr_array_free_hard, *addrs);
}

cur = res;
addr_cnt = 0;
while (cur && addr_cnt < *max_addrs) {
cur_addr = &(*addr)[addr_cnt];
memcpy (&cur_addr->addr, cur->ai_addr,
MIN (sizeof (cur_addr->addr), cur->ai_addrlen));
cur_addr->af = cur->ai_family;
rspamd_ip_validate_af (cur_addr);
cur_addr->slen = cur->ai_addrlen;
while (cur) {
cur_addr = rspamd_inet_address_from_sa (cur->ai_addr,
cur->ai_addrlen);

if (cur_addr != NULL) {
g_ptr_array_add (*addrs, cur_addr);
}
cur = cur->ai_next;
addr_cnt ++;
}

*max_addrs = addr_cnt;

freeaddrinfo (res);
}
else {
@@ -515,21 +700,22 @@ rspamd_parse_host_port_priority_strv (gchar **tokens,
}
else {
/* Special case of unix socket, as getaddrinfo cannot deal with them */
if (pool == NULL) {
*addr = g_new0 (rspamd_inet_addr_t, 1);
}
else {
*addr = rspamd_mempool_alloc0 (pool, sizeof (rspamd_inet_addr_t));
*addrs = g_ptr_array_new_full (1,
(GDestroyNotify)rspamd_inet_address_destroy);

if (pool != NULL) {
rspamd_mempool_add_destructor (pool,
rspamd_ptr_array_free_hard, *addrs);
}

cur_addr = *addr;
if (!rspamd_parse_inet_address (cur_addr, tokens[0])) {
if (!rspamd_parse_inet_address (&cur_addr, tokens[0])) {
msg_err ("cannot parse unix socket definition %s: %s",
tokens[0],
strerror (errno));
goto err;
}
*max_addrs = 1;

g_ptr_array_add (*addrs, cur_addr);
}

/* Restore errno */
@@ -552,8 +738,7 @@ err:
gboolean
rspamd_parse_host_port_priority (
const gchar *str,
rspamd_inet_addr_t **addr,
guint *max_addrs,
GPtrArray **addrs,
guint *priority,
gchar **name,
guint default_port,
@@ -567,7 +752,7 @@ rspamd_parse_host_port_priority (
return FALSE;
}

ret = rspamd_parse_host_port_priority_strv (tokens, addr, max_addrs,
ret = rspamd_parse_host_port_priority_strv (tokens, addrs,
priority, name, default_port, pool);

g_strfreev (tokens);
@@ -577,12 +762,104 @@ rspamd_parse_host_port_priority (

gboolean
rspamd_parse_host_port (const gchar *str,
rspamd_inet_addr_t **addr,
guint *max_addrs,
GPtrArray **addrs,
gchar **name,
guint default_port,
rspamd_mempool_t *pool)
{
return rspamd_parse_host_port_priority (str, addr, max_addrs, NULL,
return rspamd_parse_host_port_priority (str, addrs, NULL,
name, default_port, pool);
}


guchar*
rspamd_inet_address_get_radix_key (const rspamd_inet_addr_t *addr, guint *klen)
{
guchar *res = NULL;
static struct in_addr local = {INADDR_LOOPBACK};

g_assert (addr != NULL);
g_assert (klen != NULL);

if (addr->af == AF_INET) {
*klen = sizeof (struct in_addr);
res = (guchar *)&addr->u.in.addr.s4.sin_addr;
}
else if (addr->af == AF_INET6) {
*klen = sizeof (struct in6_addr);
res = (guchar *)&addr->u.in.addr.s6.sin6_addr;
}
else if (addr->af == AF_UNIX) {
*klen = sizeof (struct in_addr);
res = (guchar *)&local;
}

return res;
}


rspamd_inet_addr_t *
rspamd_inet_address_new (int af, const void *init)
{
rspamd_inet_addr_t *addr;

addr = rspamd_inet_addr_create (af);

if (init != NULL) {
if (af == AF_UNIX) {
/* Init is a path */
rspamd_strlcpy (addr->u.un->addr.sun_path, init,
sizeof (addr->u.un->addr.sun_path));
#if defined(FREEBSD) || defined(__APPLE__)
addr->u.un->addr.sun_len = SUN_LEN (&addr->u.un->addr);
#endif
}
else if (af == AF_INET) {
memcpy (&addr->u.in.addr.s4.sin_addr, init, sizeof (struct in_addr));
}
else if (af == AF_INET6) {
memcpy (&addr->u.in.addr.s6.sin6_addr, init, sizeof (struct in6_addr));
}
}

return addr;
}

rspamd_inet_addr_t *
rspamd_inet_address_from_sa (const struct sockaddr *sa, socklen_t slen)
{
rspamd_inet_addr_t *addr;

g_assert (sa != NULL);
g_assert (slen >= sizeof (struct sockaddr));

addr = rspamd_inet_addr_create (sa->sa_family);

if (sa->sa_family == AF_UNIX) {
/* Init is a path */
const struct sockaddr_un *un = (const struct sockaddr_un *)sa;

g_assert (slen >= SUN_LEN (un));

rspamd_strlcpy (addr->u.un->addr.sun_path, un->sun_path,
sizeof (addr->u.un->addr.sun_path));
#if defined(FREEBSD) || defined(__APPLE__)
addr->u.un->addr.sun_len = un->sun_len;
#endif
}
else if (sa->sa_family == AF_INET) {
g_assert (slen >= sizeof (struct sockaddr_in));
memcpy (&addr->u.in.addr.s4, sa, sizeof (struct sockaddr_in));
}
else if (sa->sa_family == AF_INET6) {
g_assert (slen >= sizeof (struct sockaddr_in6));
memcpy (&addr->u.in.addr.s6, sa, sizeof (struct sockaddr_in6));
}
else {
/* XXX: currently we cannot deal with other AF */
g_assert (0);
}

return addr;
}


+ 70
- 30
src/libutil/addr.h View File

@@ -27,25 +27,26 @@
#include "mem_pool.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;
gint af;
/* Unix socket specific */
gint mode;
uid_t owner;
gid_t group;
} rspamd_inet_addr_t;
* Opaque structure
*/
typedef struct rspamd_inet_addr_s rspamd_inet_addr_t;

/**
* Create new inet address structure based on the address familiy and opaque init pointer
* @param af
* @param init
* @return new inet addr
*/
rspamd_inet_addr_t * rspamd_inet_address_new (int af, const void *init);

/**
* Create new inet address structure from struct sockaddr
* @param sa
* @param slen
* @return
*/
rspamd_inet_addr_t * rspamd_inet_address_from_sa (const struct sockaddr *sa,
socklen_t slen);

/**
* Try to parse address from string
@@ -53,7 +54,7 @@ typedef struct _rspamd_inet_addr_s {
* @param src IP string representation
* @return TRUE if addr has been parsed
*/
gboolean rspamd_parse_inet_address (rspamd_inet_addr_t *target,
gboolean rspamd_parse_inet_address (rspamd_inet_addr_t **target,
const char *src);

/**
@@ -61,14 +62,52 @@ gboolean rspamd_parse_inet_address (rspamd_inet_addr_t *target,
* @param addr
* @return statically allocated string pointer (not thread safe)
*/
const char * rspamd_inet_address_to_string (rspamd_inet_addr_t *addr);
const char * rspamd_inet_address_to_string (const 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);
uint16_t rspamd_inet_address_get_port (const rspamd_inet_addr_t *addr);

/**
* Returns address family of inet address
* @param addr
* @return
*/
gint rspamd_inet_address_get_af (const rspamd_inet_addr_t *addr);


/**
* Makes a radix key from inet address
* @param addr
* @param klen
* @return
*/
guchar * rspamd_inet_address_get_radix_key (const rspamd_inet_addr_t *addr, guint *klen);

/**
* Receive data from an unconnected socket and fill the inet_addr structure if needed
* @param fd
* @param buf
* @param len
* @param target
* @return same as recvfrom(2)
*/
gssize rspamd_inet_address_recvfrom (gint fd, void *buf, gsize len, gint fl,
rspamd_inet_addr_t **target);

/**
* Send data via unconnected socket using the specified inet_addr structure
* @param fd
* @param buf
* @param len
* @param target
* @return
*/
gssize rspamd_inet_address_sendto (gint fd, const void *buf, gsize len, gint fl,
const rspamd_inet_addr_t *addr);

/**
* Set port for inet address
@@ -81,7 +120,7 @@ void rspamd_inet_address_set_port (rspamd_inet_addr_t *addr, uint16_t port);
* @param async perform operations asynchronously
* @return newly created and connected socket
*/
int rspamd_inet_address_connect (rspamd_inet_addr_t *addr, gint type,
int rspamd_inet_address_connect (const rspamd_inet_addr_t *addr, gint type,
gboolean async);

/**
@@ -91,7 +130,7 @@ int rspamd_inet_address_connect (rspamd_inet_addr_t *addr, gint type,
* @param async
* @return
*/
int rspamd_inet_address_listen (rspamd_inet_addr_t *addr, gint type,
int rspamd_inet_address_listen (const 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
@@ -99,18 +138,18 @@ int rspamd_inet_address_listen (rspamd_inet_addr_t *addr, gint type,
* @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);
gboolean rspamd_ip_is_valid (const rspamd_inet_addr_t *addr);

/**
* Accept from listening socket filling addr structure
* @param sock listening socket
* @param addr
* @param addr allocated inet addr structur
* @return
*/
gint rspamd_accept_from_socket (gint sock, rspamd_inet_addr_t *addr);
gint rspamd_accept_from_socket (gint sock, rspamd_inet_addr_t **addr);

gboolean rspamd_parse_host_port_priority_strv (gchar **tokens,
rspamd_inet_addr_t **addr, guint *max_addrs, guint *priority,
GPtrArray **addrs, guint *priority,
gchar **name, guint default_port, rspamd_mempool_t *pool);

/**
@@ -121,7 +160,7 @@ gboolean rspamd_parse_host_port_priority_strv (gchar **tokens,
* @return TRUE if string was parsed
*/
gboolean rspamd_parse_host_port_priority (const gchar *str,
rspamd_inet_addr_t **addr, guint *max_addrs,
GPtrArray **addrs,
guint *priority, gchar **name, guint default_port,
rspamd_mempool_t *pool);

@@ -132,8 +171,9 @@ gboolean rspamd_parse_host_port_priority (const gchar *str,
* @return TRUE if string was parsed
*/
gboolean rspamd_parse_host_port (const gchar *str,
rspamd_inet_addr_t **addr, guint *max_addrs,
GPtrArray **addrs,
gchar **name, guint default_port, rspamd_mempool_t *pool);

void rspamd_inet_address_destroy (rspamd_inet_addr_t *addr);

#endif /* ADDR_H_ */

Loading…
Cancel
Save