11 Commits

Author SHA1 Message Date
Sam Hocevar
f91e34c3af Release version 0.72. 2021-02-16 09:27:25 +01:00
Sam Hocevar
5e8be95d8a Fix a configuration parsing bug. 2021-02-16 09:22:25 +01:00
Sam Hocevar
7887c17096 Fix Mac OS X build. 2021-02-14 14:41:15 +01:00
Sam Hocevar
432aa4d230 Release version 0.71. 2021-02-14 12:12:53 +01:00
Sam Hocevar
b00f175fa4 Fix HTML documentation generation. 2021-02-14 12:09:26 +01:00
Sam Hocevar
6a1e7e75a3 Prepare version 0.71. 2021-02-14 12:06:31 +01:00
Sam Hocevar
7f76652af9 Improve documentation. 2021-02-14 12:05:29 +01:00
Sam Hocevar
bb0d64ed5d Refactor code to avoid duplication. 2021-02-14 11:59:16 +01:00
Sam Hocevar
3b33f45925 Merge branch 'feature-ipv6-support' into main 2021-02-14 11:41:54 +01:00
Sam Hocevar
878c804d32 Update changelog for upcoming version 0.71. 2021-02-14 11:39:04 +01:00
Sam Hocevar
f9f5aeda80 Properly release the lexer context after reading the configuration. 2021-02-14 11:20:37 +01:00
13 changed files with 127 additions and 105 deletions

View File

@@ -1,11 +1,24 @@
## Version 0.70
## Version 0.72 (2021/02/16)
* fixed a configuration parsing bug making 0.71 almost unusable
## Version 0.71 (2021/02/14)
* IPv6 support
* fixed a display overflow in data usage statistics
* made the configuration parser more tolerant with service names that contain
dashes (e.g. snmp-trap) or hostnames with underscores (e.g. \_http.example.com).
* create the log file if it does not exist
* new Visual Studio project file
## Version 0.70 (2017/09/09)
* UDP support
* source address binding support
* use a real grammar for the configuration file and get rid of the hand-made
parser
## Version 0.63
## Version 0.63 (2017/07/19)
* added a `-f` flag to run in the foreground
* quit cleanly when `SIGINT` is received

View File

@@ -3,13 +3,17 @@ AUTOMAKE_OPTIONS = foreign dist-bzip2
SUBDIRS = src
EXTRA_DIST = bootstrap COPYING CHANGES.md README.md index.html \
EXTRA_DIST = bootstrap COPYING CHANGES.md README.md index.html rinetd.vcxproj \
$(man_MANS) $(sysconf_DATA)
man_MANS = rinetd.8
sysconf_DATA = rinetd.conf
noinst_DATA = index.html
# If roffit is available, regenerate index.html
index.html: rinetd.8
if which roffit >/dev/null 2>&1; then roffit < $^ > $@; else touch $@; fi
# This is for Travis CI; we dont have a testsuite yet.
test:

View File

@@ -1,6 +1,6 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.52)
AC_INIT(rinetd, 0.70, sam@hocevar.net)
AC_INIT(rinetd, 0.72, sam@hocevar.net)
AC_CONFIG_AUX_DIR(.auto)
AC_CONFIG_SRCDIR([src/rinetd.c])
AC_CONFIG_HEADER([src/config.h])

View File

@@ -79,7 +79,7 @@ p.roffit {
<p class="level0">Ports default to TCP. To specify the protocol, append <span Class="emphasis">/udp</span> or <span Class="emphasis">/tcp</span> to the port number:
<p class="level0"><span Class="bold"> 206.125.69.81 80/tcp 10.1.1.2 8000/udp</span>
<p class="level0">Service names can be specified instead of port numbers. On most systems, service names are defined in the file <span Class="emphasis">/etc/services</span>.
<p class="level0">Both IP addresses and hostnames are accepted for bindaddress and connectaddress.
<p class="level0">Both IP addresses and hostnames are accepted for bindaddress and connectaddress, including IPv6.
<p class="level0">
<p class="level0"><a name="UDP"></a><h2 class="nroffsh">UDP timeout option</h2>
<p class="level0">Since UDP is a connectionless protocol, a timeout is necessary or forwarding connections may accumulate with time and exhaust resources. By default, if no data is sent or received on a UDP connection for 72 seconds, the other connection is closed. This value can be changed using the <span Class="emphasis">timeout</span> option:
@@ -87,8 +87,8 @@ p.roffit {
<p class="level0">This rule will forward all data received on UDP port 8000 to host 10.1.1.2 on TCP port 80, and will close the connection after no data is received on the UDP port for 3600 seconds.
<p class="level0"><a name="Source"></a><h2 class="nroffsh">Source address option</h2>
<p class="level0">A forwarding rule option allows to bind to a specific local address when sending data to the other end. This is done using the <span Class="emphasis">src</span> option:
<p class="level0"><span Class="bold"> 192.168.1.1 80 10.1.1.2 80 [src=192.168.1.2]</span>
<p class="level0">Assuming the local host has two IP addresses, 192.168.1.1 and 192.168.1.2, this rule ensures that forwarded packets are sent using source address 192.168.1.2.
<p class="level0"><span Class="bold"> 192.168.1.1 80 10.1.1.127 80 [src=10.1.1.2]</span>
<p class="level0">Assuming the local host has two IP addresses, 10.1.1.1 and 10.1.1.2, this rule ensures that forwarded packets are sent using source address 10.1.1.2.
<p class="level0"><a name="ALLOW"></a><h2 class="nroffsh">ALLOW AND DENY RULES</h2>
<p class="level0">Configuration files can also contain allow and deny rules.
<p class="level0">Allow rules which appear before the first forwarding rule are applied globally: if at least one global allow rule exists, and the address of a new connection does not satisfy at least one of the global allow rules, that connection is immediately rejected, regardless of any other rules.
@@ -130,7 +130,7 @@ p.roffit {
<p class="level0">The server redirected to is not able to identify the host the client really came from. This cannot be corrected; however, the log produced by <span Class="bold">rinetd</span> provides a way to obtain this information. Under Unix, Sockets would theoretically lose data when closed with SO_LINGER turned off, but in Linux this is not the case (kernel source comments support this belief on my part). On non-Linux Unix platforms, alternate code which uses a different trick to work around blocking close() is provided, but this code is untested.
<p class="level0">The logging is inadequate. The duration of each connection should be logged. <a name="LICENSE"></a><h2 class="nroffsh">LICENSE</h2>
<p class="level0">Copyright (c) 1997, 1998, 1999, Thomas Boutell and Boutell.Com, Inc.
<p class="level0">Copyright (c) 2003-2017 Sam Hocevar
<p class="level0">Copyright (c) 2003-2021 Sam Hocevar
<p class="level0">This software is released for free use under the terms of the GNU General Public License, version 2 or higher. NO WARRANTY IS EXPRESSED OR IMPLIED. USE THIS SOFTWARE AT YOUR OWN RISK. <a name="CONTACT"></a><h2 class="nroffsh">CONTACT INFORMATION</h2>
<p class="level0">See https://github.com/samhocevar/rinetd/releases for the latest release.
<p class="level0">Thomas Boutell can be reached by email: boutell@boutell.com

View File

@@ -1,4 +1,4 @@
.TH rinetd 8 "2017-09-09" "rinetd 0.70"
.TH rinetd 8 "2021-02-12" "rinetd 0.72"
.SH NAME
rinetd \- internet redirection server
@@ -80,7 +80,7 @@ Service names can be specified instead of port numbers. On most systems,
service names are defined in the file \fI/etc/services\fR.
.PP
Both IP addresses and hostnames are accepted for
bindaddress and connectaddress.
bindaddress and connectaddress, including IPv6.
.PP
.SS UDP timeout option
@@ -99,10 +99,10 @@ the UDP port for 3600 seconds.
A forwarding rule option allows to bind to a specific local address when
sending data to the other end. This is done using the \fIsrc\fR option:
.PP
\fB 192.168.1.1 80 10.1.1.2 80 [src=192.168.1.2]\fR
\fB 192.168.1.1 80 10.1.1.127 80 [src=10.1.1.2]\fR
.PP
Assuming the local host has two IP addresses, 192.168.1.1 and 192.168.1.2, this
rule ensures that forwarded packets are sent using source address 192.168.1.2.
Assuming the local host has two IP addresses, 10.1.1.1 and 10.1.1.2, this
rule ensures that forwarded packets are sent using source address 10.1.1.2.
.SH ALLOW AND DENY RULES
Configuration files can also contain allow and deny rules.
@@ -216,7 +216,7 @@ The logging is inadequate. The duration of each connection should be logged.
.SH LICENSE
Copyright (c) 1997, 1998, 1999, Thomas Boutell and Boutell.Com, Inc.
.PP
Copyright (c) 2003\-2017 Sam Hocevar
Copyright (c) 2003\-2021 Sam Hocevar
.PP
This software is released for free use under the terms of
the GNU General Public License, version 2 or higher. NO WARRANTY

View File

@@ -7,6 +7,8 @@
#
# allow 192.168.2.*
# deny 192.168.2.1?
# allow fe80:*
# deny 2001:618:*:e43f
#
@@ -17,6 +19,8 @@
#
# bindadress bindport connectaddress connectport options...
# 0.0.0.0 80 192.168.1.2 80
# ::1 80 192.168.1.2 80
# 0.0.0.0 80 fe80::1 80
# 127.0.0.1 4000 127.0.0.1 3000
# 127.0.0.1 4000/udp 127.0.0.1 22 [timeout=1200]
# 127.0.0.1 8000/udp 192.168.1.2 8000/udp [src=192.168.1.2,timeout=1200]

View File

@@ -78,7 +78,7 @@
<SDLCheck>true</SDLCheck>
<CompileAs>CompileAsC</CompileAs>
<ConformanceMode>true</ConformanceMode>
<PreprocessorDefinitions>_CONSOLE;PACKAGE_VERSION="0.70";_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CONSOLE;PACKAGE_VERSION="0.72";_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>

View File

@@ -14,14 +14,11 @@ BUILT_SOURCES = parse.c
parse.c: parse.peg
if which leg >/dev/null 2>&1; then leg -o $@ $^; else touch $@; fi
# If roffit is available, regenerate index.html
index.html: rinetd.8
if which roffit >/dev/null 2>&1; then roffit < $^ > $@; else touch $@; fi
# _POSIX_C_SOURCE is for SA_RESTART and others
# _DARWIN_C_SOURCE is for NI_MAXHOST on OS X
# _XOPEN_SOURCE is for struct sigaction
# _GNU_SOURCE is for h_errno and gethostbyname-related macros
___rinetd_CFLAGS = -std=c99 \
-D_XOPEN_SOURCE -D_GNU_SOURCE -D_POSIX_C_SOURCE=200809L \
___rinetd_CFLAGS = -std=c99 -D_POSIX_C_SOURCE=200809L \
-D_XOPEN_SOURCE -D_GNU_SOURCE -D_DARWIN_C_SOURCE \
-Wall -Wextra -Wwrite-strings

View File

@@ -32,8 +32,13 @@ void setSocketDefaults(SOCKET fd) {
#endif
}
int getSocketType(int protocol) {
return protocol == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
struct addrinfo getAddrInfoHint(int protocol) {
return (struct addrinfo) {
.ai_family = AF_UNSPEC,
.ai_protocol = protocol,
.ai_socktype = protocol == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM,
.ai_flags = AI_PASSIVE,
};
}
int sameSocketAddress(struct sockaddr_storage *a, struct sockaddr_storage *b) {

View File

@@ -63,6 +63,10 @@
# ifndef WSAEAGAIN
# define WSAEAGAIN WSAEWOULDBLOCK
# endif
# ifdef gai_strerror
# undef gai_strerror
# define gai_strerror gai_strerrorA
# endif
#else
/* Windows sockets compatibility defines */
# define INVALID_SOCKET (-1)
@@ -81,6 +85,6 @@ static inline int GetLastError(void) {
#endif /* _WIN32 */
void setSocketDefaults(SOCKET fd);
int getSocketType(int protocol);
struct addrinfo getAddrInfoHint(int protocol);
int sameSocketAddress(struct sockaddr_storage *a, struct sockaddr_storage *b);
uint16_t getPort(struct addrinfo* ai);

View File

@@ -356,7 +356,7 @@ YY_ACTION(void) yy_1_sol(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_sol\n"));
{
#line 150
#line 156
++yy->currentLine; ;
}
#undef yythunkpos
@@ -370,7 +370,7 @@ YY_ACTION(void) yy_1_invalid_syntax(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_invalid_syntax\n"));
{
#line 125
#line 131
fprintf(stderr, "rinetd: invalid syntax at line %d: %s\n",
yy->currentLine, yytext);
@@ -388,7 +388,7 @@ YY_ACTION(void) yy_1_logcommon(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_logcommon\n"));
{
#line 120
#line 126
logFormatCommon = 1;
;
@@ -404,7 +404,7 @@ YY_ACTION(void) yy_1_pidlogfile(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_pidlogfile\n"));
{
#line 112
#line 118
pidLogFileName = strdup(yytext);
if (!pidLogFileName) {
@@ -423,7 +423,7 @@ YY_ACTION(void) yy_1_logfile(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_logfile\n"));
{
#line 104
#line 110
logFileName = strdup(yytext);
if (!logFileName) {
@@ -442,7 +442,7 @@ YY_ACTION(void) yy_1_auth_key(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_auth_key\n"));
{
#line 101
#line 107
yy->isAuthAllow = (yytext[0] == 'a'); ;
}
#undef yythunkpos
@@ -456,7 +456,7 @@ YY_ACTION(void) yy_1_auth_rule(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_auth_rule\n"));
{
#line 79
#line 85
allRules = (Rule *)
realloc(allRules, sizeof(Rule) * (allRulesCount + 1));
@@ -490,7 +490,7 @@ YY_ACTION(void) yy_3_proto(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_3_proto\n"));
{
#line 76
#line 82
yy->tmpProto = IPPROTO_TCP; ;
}
#undef yythunkpos
@@ -504,7 +504,7 @@ YY_ACTION(void) yy_2_proto(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_2_proto\n"));
{
#line 75
#line 81
yy->tmpProto = IPPROTO_UDP; ;
}
#undef yythunkpos
@@ -518,7 +518,7 @@ YY_ACTION(void) yy_1_proto(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_proto\n"));
{
#line 74
#line 80
yy->tmpProto = IPPROTO_TCP; ;
}
#undef yythunkpos
@@ -532,7 +532,7 @@ YY_ACTION(void) yy_1_port(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_port\n"));
{
#line 73
#line 79
yy->tmpPort = strdup(yytext); ;
}
#undef yythunkpos
@@ -546,7 +546,7 @@ YY_ACTION(void) yy_1_option_source(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_option_source\n"));
{
#line 69
#line 75
yy->sourceAddress = strdup(yytext); ;
}
#undef yythunkpos
@@ -560,7 +560,7 @@ YY_ACTION(void) yy_1_option_timeout(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_option_timeout\n"));
{
#line 68
#line 74
yy->serverTimeout = atoi(yytext); ;
}
#undef yythunkpos
@@ -574,7 +574,7 @@ YY_ACTION(void) yy_1_connect_port(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_connect_port\n"));
{
#line 63
#line 69
yy->connectPort = yy->tmpPort; yy->connectProto = yy->tmpProto; ;
}
#undef yythunkpos
@@ -588,7 +588,7 @@ YY_ACTION(void) yy_1_bind_port(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_bind_port\n"));
{
#line 62
#line 68
yy->bindPort = yy->tmpPort; yy->bindProto = yy->tmpProto; ;
}
#undef yythunkpos
@@ -602,7 +602,7 @@ YY_ACTION(void) yy_1_connect_address(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_connect_address\n"));
{
#line 61
#line 67
yy->connectAddress = strdup(yytext); ;
}
#undef yythunkpos
@@ -616,7 +616,7 @@ YY_ACTION(void) yy_1_bind_address(yycontext *yy, char *yytext, int yyleng)
#define yythunkpos yy->__thunkpos
yyprintf((stderr, "do yy_1_bind_address\n"));
{
#line 60
#line 66
yy->bindAddress = strdup(yytext); ;
}
#undef yythunkpos
@@ -636,7 +636,13 @@ YY_ACTION(void) yy_1_server_rule(yycontext *yy, char *yytext, int yyleng)
yy->connectAddress, yy->connectPort, yy->connectProto,
yy->serverTimeout > 0 ? yy->serverTimeout : RINETD_DEFAULT_UDP_TIMEOUT,
yy->sourceAddress);
free(yy->bindAddress);
free(yy->connectAddress);
free(yy->sourceAddress);
yy->bindAddress = yy->connectAddress = yy->sourceAddress = NULL;
free(yy->bindPort);
free(yy->connectPort);
yy->bindPort = yy->connectPort = NULL;
yy->serverTimeout = 0;
;
}
@@ -1394,7 +1400,7 @@ YY_PARSE(yycontext *) YYRELEASE(yycontext *yyctx)
}
#endif
#line 154 "parse.peg"
#line 160 "parse.peg"
void parseConfiguration(char const *file)
@@ -1412,6 +1418,7 @@ void parseConfiguration(char const *file)
"on file %s, line %d.\n", file, -1);
exit(1);
}
yyrelease(&ctx);
fclose(in);

View File

@@ -53,7 +53,13 @@ server-rule = bind-address - bind-port - connect-address - connect-port (-? se
yy->connectAddress, yy->connectPort, yy->connectProto,
yy->serverTimeout > 0 ? yy->serverTimeout : RINETD_DEFAULT_UDP_TIMEOUT,
yy->sourceAddress);
free(yy->bindAddress);
free(yy->connectAddress);
free(yy->sourceAddress);
yy->bindAddress = yy->connectAddress = yy->sourceAddress = NULL;
free(yy->bindPort);
free(yy->connectPort);
yy->bindPort = yy->connectPort = NULL;
yy->serverTimeout = 0;
}
@@ -168,6 +174,7 @@ void parseConfiguration(char const *file)
"on file %s, line %d.\n", file, -1);
exit(1);
}
yyrelease(&ctx);
fclose(in);

View File

@@ -261,93 +261,74 @@ void addServer(char *bindAddress, char *bindPort, int bindProtocol,
int serverTimeout, char *sourceAddress)
{
ServerInfo si = {
.fromHost = bindAddress,
.toHost = connectAddress,
.fromHost = strdup(bindAddress),
.toHost = strdup(connectAddress),
.serverTimeout = serverTimeout,
};
/* Make a server socket */
struct addrinfo hints =
{
.ai_family = AF_UNSPEC,
.ai_protocol = bindProtocol,
.ai_socktype = getSocketType(bindProtocol),
.ai_flags = AI_PASSIVE,
};
struct addrinfo *servinfo;
int ret = getaddrinfo(bindAddress, bindPort, &hints, &servinfo);
struct addrinfo hints = getAddrInfoHint(bindProtocol), *ai;
int ret = getaddrinfo(bindAddress, bindPort, &hints, &ai);
if (ret != 0) {
fprintf(stderr, "rinetd: getaddrinfo error: %s\n", gai_strerrorA(ret));
fprintf(stderr, "rinetd: getaddrinfo error: %s\n", gai_strerror(ret));
exit(1);
}
for (struct addrinfo *it = servinfo; it; it = it->ai_next) {
si.fd = socket(it->ai_family, it->ai_socktype, it->ai_protocol);
if (si.fd == INVALID_SOCKET) {
syslog(LOG_ERR, "couldn't create server socket! (%m)\n");
freeaddrinfo(servinfo);
exit(1);
}
int tmp = 1;
setsockopt(si.fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&tmp, sizeof(tmp));
if (bind(si.fd, it->ai_addr, it->ai_addrlen) == SOCKET_ERROR) {
syslog(LOG_ERR, "couldn't bind to address %s port %s (%m)\n",
bindAddress, bindPort);
closesocket(si.fd);
freeaddrinfo(servinfo);
exit(1);
}
if (bindProtocol == IPPROTO_TCP) {
if (listen(si.fd, RINETD_LISTEN_BACKLOG) == SOCKET_ERROR) {
/* Warn -- don't exit. */
syslog(LOG_ERR, "couldn't listen to address %s port %s (%m)\n",
bindAddress, bindPort);
/* XXX: check whether this is correct */
closesocket(si.fd);
}
/* Make socket nonblocking in TCP mode only, otherwise
we may miss some data. */
setSocketDefaults(si.fd);
}
si.fromAddrInfo = it;
break;
si.fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (si.fd == INVALID_SOCKET) {
syslog(LOG_ERR, "couldn't create server socket! (%m)\n");
freeaddrinfo(ai);
exit(1);
}
int tmp = 1;
setsockopt(si.fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&tmp, sizeof(tmp));
if (bind(si.fd, ai->ai_addr, ai->ai_addrlen) == SOCKET_ERROR) {
syslog(LOG_ERR, "couldn't bind to address %s port %s (%m)\n",
bindAddress, bindPort);
closesocket(si.fd);
freeaddrinfo(ai);
exit(1);
}
if (bindProtocol == IPPROTO_TCP) {
if (listen(si.fd, RINETD_LISTEN_BACKLOG) == SOCKET_ERROR) {
/* Warn -- don't exit. */
syslog(LOG_ERR, "couldn't listen to address %s port %s (%m)\n",
bindAddress, bindPort);
/* XXX: check whether this is correct */
closesocket(si.fd);
}
/* Make socket nonblocking in TCP mode only, otherwise
we may miss some data. */
setSocketDefaults(si.fd);
}
si.fromAddrInfo = ai;
/* Resolve destination address. */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_protocol = connectProtocol;
hints.ai_socktype = getSocketType(connectProtocol);
hints.ai_flags = AI_PASSIVE;
ret = getaddrinfo(connectAddress, connectPort, &hints, &servinfo);
hints = getAddrInfoHint(connectProtocol);
ret = getaddrinfo(connectAddress, connectPort, &hints, &ai);
if (ret != 0) {
fprintf(stderr, "rinetd: getaddrinfo error: %s\n", gai_strerrorA(ret));
fprintf(stderr, "rinetd: getaddrinfo error: %s\n", gai_strerror(ret));
freeaddrinfo(si.fromAddrInfo);
closesocket(si.fd);
exit(1);
}
si.toAddrInfo = servinfo;
si.toAddrInfo = ai;
/* 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);
hints = getAddrInfoHint(connectProtocol);
ret = getaddrinfo(sourceAddress, NULL, &hints, &ai);
if (ret != 0) {
fprintf(stderr, "rinetd: getaddrinfo error: %s\n", gai_strerrorA(ret));
fprintf(stderr, "rinetd: getaddrinfo error: %s\n", gai_strerror(ret));
freeaddrinfo(si.fromAddrInfo);
freeaddrinfo(si.toAddrInfo);
exit(1);
}
si.sourceAddrInfo = servinfo;
si.sourceAddrInfo = ai;
}
#ifndef _WIN32