Use getaddrinfo/getnameinfo instead of deprecated methods

This commit is contained in:
2023-01-29 20:31:27 +01:00
parent ad6ffe5425
commit 6f0371c46f
4 changed files with 107 additions and 72 deletions

View File

@ -19,7 +19,6 @@
#include <errno.h>
#include <openssl/err.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <semaphore.h>
static SSL_CTX *proxy_ctx = NULL;
@ -303,48 +302,10 @@ int proxy_response_header(http_req *req, http_res *res, host_config_t *conf) {
static int proxy_connect(proxy_ctx_t *proxy, host_config_t *conf, http_res *res, http_status_ctx *ctx, char *err_msg) {
char err_buf[256], addr_buf[1024];
info(BLUE_STR "Connecting to " BLD_STR "[%s]:%i" CLR_STR BLUE_STR "...", conf->proxy.hostname, conf->proxy.port);
int fd;
if ((fd = socket(AF_INET6, SOCK_STREAM, 0)) == -1) {
error("Unable to create socket");
res->status = http_get_status(500);
ctx->origin = INTERNAL;
return -1;
}
sock_init(&proxy->proxy, fd, 0);
if (sock_set_socket_timeout(&proxy->proxy, 1) != 0 || sock_set_timeout(&proxy->proxy, SERVER_TIMEOUT_INIT) != 0) {
res->status = http_get_status(500);
ctx->origin = INTERNAL;
error("Unable to set timeout for reverse proxy socket");
sprintf(err_msg, "Unable to set timeout for reverse proxy socket: %s", error_str(errno, err_buf, sizeof(err_buf)));
return -1;
}
struct hostent *host_ent = gethostbyname2(conf->proxy.hostname, AF_INET6);
if (host_ent == NULL) {
host_ent = gethostbyname2(conf->proxy.hostname, AF_INET);
if (host_ent == NULL) {
res->status = http_get_status(502);
ctx->origin = SERVER_REQ;
error("Unable to connect to server: Name or service not known");
sprintf(err_msg, "Unable to connect to server: Name or service not known.");
return -1;
}
}
struct sockaddr_in6 address = {.sin6_family = AF_INET6, .sin6_port = htons(conf->proxy.port)};
if (host_ent->h_addrtype == AF_INET6) {
memcpy(&address.sin6_addr, host_ent->h_addr_list[0], host_ent->h_length);
} else if (host_ent->h_addrtype == AF_INET) {
unsigned char addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0};
memcpy(addr + 12, host_ent->h_addr_list[0], host_ent->h_length);
memcpy(&address.sin6_addr, addr, 16);
}
inet_ntop(address.sin6_family, (void *) &address.sin6_addr, addr_buf, sizeof(addr_buf));
info(BLUE_STR "Connecting to " BLD_STR "[%s]:%i" CLR_STR BLUE_STR "...", addr_buf, conf->proxy.port);
if (connect(proxy->proxy.socket, (struct sockaddr *) &address, sizeof(address)) < 0) {
if ((fd = sock_connect(conf->proxy.hostname, conf->proxy.port, SERVER_TIMEOUT_INIT, addr_buf, sizeof(addr_buf))) == -1) {
if (errno == ETIMEDOUT || errno == EINPROGRESS) {
res->status = http_get_status(504);
ctx->origin = SERVER_REQ;
@ -360,6 +321,8 @@ static int proxy_connect(proxy_ctx_t *proxy, host_config_t *conf, http_res *res,
return -1;
}
sock_init(&proxy->proxy, fd, 0);
if (sock_set_timeout(&proxy->proxy, SERVER_TIMEOUT) != 0) {
res->status = http_get_status(500);
ctx->origin = INTERNAL;
@ -389,6 +352,7 @@ static int proxy_connect(proxy_ctx_t *proxy, host_config_t *conf, http_res *res,
proxy->initialized = 1;
proxy->cnx_s = clock_micros();
proxy->host = conf->name;
info(BLUE_STR "Established new connection with " BLD_STR "[%s]:%i", addr_buf, conf->proxy.port);
return 0;

View File

@ -9,6 +9,7 @@
#include "sock.h"
#include "utils.h"
#include "error.h"
#include "../logger.h"
#include <errno.h>
#include <openssl/ssl.h>
@ -18,8 +19,9 @@
#include <openssl/err.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <netdb.h>
static void ssl_error(unsigned long err) {
static void sock_ssl_error(unsigned long err) {
if (err == SSL_ERROR_NONE) {
errno = 0;
} else if (err == SSL_ERROR_SYSCALL) {
@ -32,7 +34,18 @@ static void ssl_error(unsigned long err) {
}
void sock_error(sock *s, int ret) {
ssl_error(SSL_get_error(s->ssl, ret));
sock_ssl_error(SSL_get_error(s->ssl, ret));
}
int sock_gai_error(int ret) {
if (ret == 0) {
errno = 0;
} else if (ret == EAI_SYSTEM) {
// errno already set
} else {
error_gai(ret);
}
return -1;
}
const char *sock_error_str(unsigned long err) {
@ -78,6 +91,85 @@ int sock_init(sock *s, int fd, int flags) {
return 0;
}
int sock_connect(const char *hostname, unsigned short port, double timeout_sec, char *addr_buf, size_t addr_buf_size) {
char buf[INET6_ADDRSTRLEN + 1];
int ret, fd, e = 0;
long timeout_micros = (long) (timeout_sec * 1000000L);
struct addrinfo *result, *rp,
hints = {
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM,
.ai_protocol = 0,
.ai_flags = 0,
};
if (addr_buf && addr_buf_size > 1)
addr_buf[0] = 0;
if ((ret = getaddrinfo(hostname, NULL, &hints, &result)) != 0)
return sock_gai_error(ret);
for (rp = result; rp != NULL; rp = rp->ai_next) {
switch (rp->ai_family) {
case AF_INET:
((struct sockaddr_in *) rp->ai_addr)->sin_port = htons(port);
inet_ntop(rp->ai_family, &((struct sockaddr_in *) rp->ai_addr)->sin_addr, buf, addr_buf_size);
break;
case AF_INET6:
((struct sockaddr_in6 *) rp->ai_addr)->sin6_port = htons(port);
inet_ntop(rp->ai_family, &((struct sockaddr_in6 *) rp->ai_addr)->sin6_addr, buf, addr_buf_size);
break;
}
debug("Trying [%s]:%i", buf, port);
if ((fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) == -1) {
if (e == 0) {
e = errno;
} else if (e != errno) {
e = -1;
}
continue;
}
if (sock_set_socket_timeout_micros(fd, timeout_micros, timeout_micros) == -1) {
close(fd);
return -1;
}
if (connect(fd, rp->ai_addr, rp->ai_addrlen) == -1) {
e = errno;
close(fd);
continue;
}
break;
}
freeaddrinfo(result);
if (addr_buf && addr_buf_size > 1 && addr_buf[0] == 0)
strncpy(addr_buf, buf, addr_buf_size);
errno = e;
return (e == 0) ? fd : -1;
}
int sock_reverse_lookup(const sock *s, char *host, size_t host_size) {
memset(host, 0, host_size);
int ret;
if ((ret = getnameinfo(&s->_addr.sock, sizeof(s->_addr), host, host_size, NULL, 0, 0)) != 0) {
if (ret == EAI_NONAME) {
return 0;
} else {
return sock_gai_error(ret);
}
}
return 0;
}
int sock_set_socket_timeout_micros(int fd, long recv_micros, long send_micros) {
struct timeval recv_to = {.tv_sec = recv_micros / 1000000, .tv_usec = recv_micros % 1000000},
send_to = {.tv_sec = send_micros / 1000000, .tv_usec = send_micros % 1000000};

View File

@ -38,6 +38,12 @@ const char *sock_error_str(unsigned long err);
int sock_init(sock *s, int fd, int enc);
int sock_connect(const char *hostname, unsigned short port, double timeout_sec, char *addr_buf, size_t addr_buf_size);
int sock_reverse_lookup(const sock *s, char *host, size_t host_size);
int sock_init_addr_str(const sock *s, char *c_addr, size_t c_addr_size, char *s_addr, size_t s_addr_size);
int sock_set_socket_timeout_micros(int fd, long recv_micros, long send_micros);
int sock_set_socket_timeout(sock *s, double sec);

View File

@ -28,32 +28,6 @@ void tcp_acceptor_func(client_ctx_t *ctx) {
}
}
static int dig(const char *addr, char *host, size_t host_size) {
char buf[1024];
FILE *out;
int ret;
sprintf(buf, "dig +short +time=1 -x %s", addr);
if ((out = popen(buf, "r")) == NULL) {
error("Unable to start dig: %s");
return -1;
}
unsigned long read = fread(buf, 1, sizeof(buf), out);
if ((ret = pclose(out)) != 0) {
error("Dig terminated with exit code %i", ret);
return -1;
}
char *ptr = memchr(buf, '\n', read);
if (ptr == buf || ptr == NULL) return -1;
ptr[-1] = 0;
strncpy(host, buf, host_size);
return 0;
}
static int tcp_acceptor(client_ctx_t *ctx) {
struct sockaddr_in6 server_addr;
@ -84,8 +58,7 @@ static int tcp_acceptor(client_ctx_t *ctx) {
sock *client = &ctx->socket;
ctx->cnx_s = clock_micros();
ctx->host[0] = 0;
dig(ctx->socket.addr, ctx->host, sizeof(ctx->host));
sock_reverse_lookup(&ctx->socket, ctx->host, sizeof(ctx->host));
ctx->cc[0] = 0;
geoip_lookup_country(&client->_addr.sock, ctx->cc);