Pārlūkot izejas kodu

Use getaddrinfo when opening sockets.

tags/0.5.5
Vsevolod Stakhov pirms 11 gadiem
vecāks
revīzija
8cc2aee885
5 mainītis faili ar 108 papildinājumiem un 104 dzēšanām
  1. 2
    2
      src/lua/lua_http.c
  2. 21
    14
      src/map.c
  3. 1
    1
      src/map.h
  4. 82
    85
      src/util.c
  5. 2
    2
      src/util.h

+ 2
- 2
src/lua/lua_http.c Parādīt failu

@@ -302,7 +302,7 @@ lua_http_dns_callback (struct rspamd_dns_reply *reply, gpointer arg)
elt = reply->elements->data;
memcpy (&ina, &elt->a.addr[0], sizeof (struct in_addr));

ud->fd = make_tcp_socket (&ina, ud->port, FALSE, TRUE);
ud->fd = make_universal_stream_socket (inet_ntoa (ina), ud->port, TRUE, FALSE, FALSE);

if (ud->fd == -1) {
lua_http_push_error (450, ud);
@@ -473,7 +473,7 @@ lua_http_make_request_common_new (lua_State *L, struct rspamd_async_session *ses
return 1;
}

ud->fd = make_tcp_socket (&ina, ud->port, FALSE, TRUE);
ud->fd = make_universal_stream_socket (inet_ntoa (ina), ud->port, TRUE, FALSE, FALSE);

if (ud->fd == -1) {
luaL_unref (L, LUA_REGISTRYINDEX, cbref);

+ 21
- 14
src/map.c Parādīt failu

@@ -68,7 +68,7 @@ connect_http (struct rspamd_map *map, struct http_map_data *data, gboolean is_as
{
gint sock;

if ((sock = make_tcp_socket (&data->addr, data->port, FALSE, is_async)) == -1) {
if ((sock = make_tcp_socket (data->addr, FALSE, is_async)) == -1) {
msg_info ("cannot connect to http server %s: %d, %s", data->host, errno, strerror (errno));
return -1;
}
@@ -1013,8 +1013,8 @@ add_map (struct config_file *cfg, const gchar *map_line, const gchar *descriptio
struct file_map_data *fdata;
struct http_map_data *hdata;
gchar portbuf[6];
gint i, s;
struct hostent *hent;
gint i, s, r;
struct addrinfo hints, *res;

/* First of all detect protocol line */
if (!check_map_proto (map_line, (int *)&proto, &def)) {
@@ -1075,6 +1075,7 @@ add_map (struct config_file *cfg, const gchar *map_line, const gchar *descriptio
}
else {
/* Default http port */
rspamd_snprintf (portbuf, sizeof (portbuf), "80");
hdata->port = 80;
/* Now separate host from path */
if ((p = strchr (def, '/')) == NULL) {
@@ -1088,19 +1089,25 @@ add_map (struct config_file *cfg, const gchar *map_line, const gchar *descriptio
hdata->path = memory_pool_strdup (cfg->map_pool, p);
hdata->rlen = 0;
/* Now try to resolve */
if (!inet_aton (hdata->host, &hdata->addr)) {
/* Resolve using dns */
hent = gethostbyname (hdata->host);
if (hent == NULL) {
msg_info ("cannot resolve: %s", hdata->host);
return FALSE;
}
else {
memcpy (&hdata->addr, hent->h_addr, sizeof (struct in_addr));
}
memset (&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* Stream socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;

if ((r = getaddrinfo (hdata->host, portbuf, &hints, &res)) == 0) {
hdata->addr = res;
memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func)freeaddrinfo, hdata->addr);
}
else {
msg_err ("address resolution for %s failed: %s", hdata->host, gai_strerror (r));
return FALSE;
}
/* Now try to connect */
if ((s = make_tcp_socket (&hdata->addr, hdata->port, FALSE, FALSE)) == -1) {
if ((s = make_tcp_socket (hdata->addr, FALSE, FALSE)) == -1) {
msg_info ("cannot connect to http server %s: %d, %s", hdata->host, errno, strerror (errno));
return FALSE;
}

+ 1
- 1
src/map.h Parādīt failu

@@ -37,7 +37,7 @@ struct file_map_data {
* Data specific to HTTP maps
*/
struct http_map_data {
struct in_addr addr;
struct addrinfo *addr;
guint16 port;
gchar *path;
gchar *host;

+ 82
- 85
src/util.c Parādīt failu

@@ -87,94 +87,88 @@ poll_sync_socket (gint fd, gint timeout, short events)
}

static gint
make_inet_socket (gint family, struct in_addr *addr, u_short port, gboolean is_server, gboolean async)
make_inet_socket (gint family, struct addrinfo *addr, gboolean is_server, gboolean async)
{
gint fd, r, optlen, on = 1, s_error;
gint serrno;
struct sockaddr_in sin;

/* Create socket */
fd = socket (AF_INET, family, 0);
if (fd == -1) {
msg_warn ("socket failed: %d, '%s'", errno, strerror (errno));
return -1;
}

if (make_socket_nonblocking (fd) < 0) {
goto out;
}

/* Set close on exec */
if (fcntl (fd, F_SETFD, FD_CLOEXEC) == -1) {
msg_warn ("fcntl failed: %d, '%s'", errno, strerror (errno));
goto out;
}

memset (&sin, 0, sizeof (sin));

/* Bind options */
sin.sin_family = AF_INET;
sin.sin_port = htons (port);
sin.sin_addr.s_addr = addr->s_addr;
struct addrinfo *cur;

cur = addr;
while (cur) {
/* Create socket */
fd = socket (cur->ai_protocol, family, 0);
if (fd == -1) {
msg_warn ("socket failed: %d, '%s'", errno, strerror (errno));
goto out;
}

if (is_server) {
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof (gint));
r = bind (fd, (struct sockaddr *)&sin, sizeof (struct sockaddr_in));
}
else {
r = connect (fd, (struct sockaddr *)&sin, sizeof (struct sockaddr_in));
}
if (make_socket_nonblocking (fd) < 0) {
goto out;
}

if (r == -1) {
if (errno != EINPROGRESS) {
msg_warn ("bind/connect failed: %d, '%s'", errno, strerror (errno));
/* Set close on exec */
if (fcntl (fd, F_SETFD, FD_CLOEXEC) == -1) {
msg_warn ("fcntl failed: %d, '%s'", errno, strerror (errno));
goto out;
}
if (!async) {
/* Try to poll */
if (poll_sync_socket (fd, CONNECT_TIMEOUT * 1000, POLLOUT) <= 0) {
errno = ETIMEDOUT;
msg_warn ("bind/connect failed: timeout");

if (is_server) {
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof (gint));
r = bind (fd, cur->ai_addr, cur->ai_addrlen);
}
else {
r = connect (fd, cur->ai_addr, cur->ai_addrlen);
}

if (r == -1) {
if (errno != EINPROGRESS) {
msg_warn ("bind/connect failed: %d, '%s'", errno, strerror (errno));
goto out;
}
else {
/* Make synced again */
if (make_socket_blocking (fd) < 0) {
if (!async) {
/* Try to poll */
if (poll_sync_socket (fd, CONNECT_TIMEOUT * 1000, POLLOUT) <= 0) {
errno = ETIMEDOUT;
msg_warn ("bind/connect failed: timeout");
goto out;
}
else {
/* Make synced again */
if (make_socket_blocking (fd) < 0) {
goto out;
}
}
}
}
}
else {
/* Still need to check SO_ERROR on socket */
optlen = sizeof (s_error);
getsockopt (fd, SOL_SOCKET, SO_ERROR, (void *)&s_error, &optlen);
if (s_error) {
errno = s_error;
goto out;
else {
/* Still need to check SO_ERROR on socket */
optlen = sizeof (s_error);
getsockopt (fd, SOL_SOCKET, SO_ERROR, (void *)&s_error, &optlen);
if (s_error) {
errno = s_error;
goto out;
}
}
break;
out:
if (fd != -1) {
close (fd);
}
fd = -1;
cur = cur->ai_next;
}


return (fd);

out:
serrno = errno;
close (fd);
errno = serrno;
return (-1);
}

gint
make_tcp_socket (struct in_addr *addr, u_short port, gboolean is_server, gboolean async)
make_tcp_socket (struct addrinfo *addr, gboolean is_server, gboolean async)
{
return make_inet_socket (SOCK_STREAM, addr, port, is_server, async);
return make_inet_socket (SOCK_STREAM, addr, is_server, async);
}

gint
make_udp_socket (struct in_addr *addr, u_short port, gboolean is_server, gboolean async)
make_udp_socket (struct addrinfo *addr, gboolean is_server, gboolean async)
{
return make_inet_socket (SOCK_DGRAM, addr, port, is_server, async);
return make_inet_socket (SOCK_DGRAM, addr, is_server, async);
}

gint
@@ -304,9 +298,9 @@ make_universal_stream_socket (const gchar *credits, guint16 port, gboolean async
{
struct sockaddr_un un;
struct stat st;
struct in_addr in;
struct hostent *he;
gint r;
struct addrinfo hints, *res;
gint r;
gchar portbuf[8];

if (*credits == '/') {
r = stat (credits, &st);
@@ -340,25 +334,28 @@ make_universal_stream_socket (const gchar *credits, guint16 port, gboolean async
}
else {
/* TCP related part */
if (inet_aton (credits, &in) == 0) {
/* Try to resolve */
if (try_resolve) {
if ((he = gethostbyname (credits)) == NULL) {
errno = ENOENT;
return -1;
}
else {
memcpy (&in, he->h_addr, sizeof (struct in_addr));
return make_tcp_socket (&in, port, is_server, async);
}
}
else {
errno = ENOENT;
return -1;
}
memset (&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* Stream socket */
hints.ai_flags = is_server ? AI_PASSIVE : 0;
hints.ai_protocol = 0; /* Any protocol */
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;

if (!try_resolve) {
hints.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV;
}

rspamd_snprintf (portbuf, sizeof (portbuf), "%d", (int)port);
if ((r = getaddrinfo (credits, portbuf, &hints, &res)) == 0) {
r = make_tcp_socket (res, is_server, async);
freeaddrinfo (res);
return r;
}
else {
return make_tcp_socket (&in, port, is_server, async);
msg_err ("address resolution for %s failed: %s", credits, gai_strerror (r));
return FALSE;
}
}
}

+ 2
- 2
src/util.h Parādīt failu

@@ -17,11 +17,11 @@ struct classifier_config;
/*
* Create socket and bind or connect it to specified address and port
*/
gint make_tcp_socket (struct in_addr *, u_short, gboolean is_server, gboolean async);
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 in_addr *, u_short, gboolean is_server, gboolean async);
gint make_udp_socket (struct addrinfo *, gboolean is_server, gboolean async);
/*
* Accept from socket
*/

Notiek ielāde…
Atcelt
Saglabāt