From b7fcf65a973c49a2ad1b9746ccc53633b2140c08 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sun, 14 Feb 2021 08:44:49 +0100 Subject: [PATCH] Use getaddrinfo() to resolve source address. --- src/rinetd.c | 39 ++++++++++++++++++++++++--------------- src/types.h | 2 +- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/rinetd.c b/src/rinetd.c index d4e89ec..5e32985 100644 --- a/src/rinetd.c +++ b/src/rinetd.c @@ -212,6 +212,9 @@ static void clearConfiguration(void) { free(srv->fromHost); free(srv->toHost); freeaddrinfo(srv->fromAddrInfo); + if (srv->sourceAddrInfo) { + freeaddrinfo(srv->sourceAddrInfo); + } } /* Free memory associated with previous set. */ free(seInfo); @@ -265,13 +268,6 @@ void addServer(char *bindAddress, char *bindPort, int bindProtocol, .serverTimeout = serverTimeout, }; - si.sourceAddr.s_addr = INADDR_ANY; - if (sourceAddress && getAddress(sourceAddress, &si.sourceAddr) < 0) { - fprintf(stderr, "rinetd: host %s could not be resolved.\n", - sourceAddress); - exit(1); - } - /* Make a server socket */ struct addrinfo hints = { @@ -324,6 +320,21 @@ void addServer(char *bindAddress, char *bindPort, int bindProtocol, break; } + /* Resolve source address if applicable */ + if (sourceAddress) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC, + hints.ai_protocol = connectProtocol, + hints.ai_socktype = getSocketType(connectProtocol), + + ret = getaddrinfo(sourceAddress, NULL, &hints, &servinfo); + if (ret != 0) { + fprintf(stderr, "rinetd: getaddrinfo error: %s\n", gai_strerror(ret)); + exit(1); + } + si.sourceAddrInfo = servinfo; + } + if (getAddress(connectAddress, &si.localAddr) < 0) { /* Warn -- don't exit. */ syslog(LOG_ERR, "host %s could not be resolved.\n", @@ -745,15 +756,13 @@ static void handleAccept(ServerInfo const *srv) if (srv->toProtocol == IPPROTO_TCP) setSocketDefaults(cnx->local.fd); - /* Bind the local socket even if we use connect() later, so that + /* Bind the local socket even though we use connect() later, so that we can specify a source address. */ - memset(&saddr, 0, sizeof(struct sockaddr_in)); - saddr.sin_family = AF_INET; - memcpy(&saddr.sin_addr, &srv->sourceAddr, sizeof(struct in_addr)); - saddr.sin_port = 0; - if (bind(cnx->local.fd, (struct sockaddr *)&saddr, - sizeof(saddr)) == SOCKET_ERROR) { - syslog(LOG_ERR, "bind(): %m\n"); + if (srv->sourceAddrInfo) { + if (bind(cnx->local.fd, srv->sourceAddrInfo->ai_addr, + srv->sourceAddrInfo->ai_addrlen) == SOCKET_ERROR) { + syslog(LOG_ERR, "bind(): %m\n"); + } } memset(&saddr, 0, sizeof(struct sockaddr_in)); diff --git a/src/types.h b/src/types.h index 6b6dce1..6e66fc3 100644 --- a/src/types.h +++ b/src/types.h @@ -31,7 +31,7 @@ struct _server_info { /* In network order, for network purposes */ struct in_addr localAddr; uint16_t localPort; - struct in_addr sourceAddr; + struct addrinfo *sourceAddrInfo; /* In ASCII and local byte order, for logging purposes */ char *fromHost, *toHost;