18 Commits

Author SHA1 Message Date
Sam Hocevar
d4e0a60119 Fix a parsing bug in the rules that would ignore the very first rule. See #23. 2021-03-02 15:25:39 +01:00
Sam Hocevar
af88e6fd4f Release version 0.73. 2021-02-19 09:56:52 +01:00
Sam Hocevar
ff41723590 Improve error reporting. Fixes #15.
- Add an error message when the configuration file could not be found.
 - Log to stderr when running in the foreground.
2021-02-19 09:12:29 +01:00
Sam Hocevar
d3dd35327f Do not log to syslog when running in the foreground. Addresses #15. 2021-02-19 08:55:45 +01:00
Sam Hocevar
49bf544bad Fix another IPv6 parsing issue. Addresses #20. 2021-02-17 14:15:54 +01:00
Sam Hocevar
1060048fe8 Refactor getaddrinfo error reporting. 2021-02-17 08:21:58 +01:00
Sam Hocevar
e3b47d086a Fix some hostnames (e.g. 123.example.com) being wrongfully parsed as IPv6. 2021-02-17 08:17:03 +01:00
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
14 changed files with 498 additions and 429 deletions

View File

@@ -1,11 +1,29 @@
## Version 0.70
## Version 0.73 (2021/02/19)
* improve error reporting
* fixed another configuration parsing bug
## 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.73, 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-19" "rinetd 0.73"
.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.73";_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

@@ -10,6 +10,7 @@
# include <config.h>
#endif
#include <stdio.h>
#include "net.h"
void setSocketDefaults(SOCKET fd) {
@@ -32,8 +33,23 @@ void setSocketDefaults(SOCKET fd) {
#endif
}
int getSocketType(int protocol) {
return protocol == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
int getAddrInfoWithProto(char *address, char *port, int protocol, struct addrinfo **ai)
{
struct addrinfo hints = {
.ai_family = AF_UNSPEC,
.ai_protocol = protocol,
.ai_socktype = protocol == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM,
.ai_flags = AI_PASSIVE,
};
int ret = getaddrinfo(address, port, &hints, ai);
if (ret != 0) {
fprintf(stderr, "rinetd: cannot resolve host \"%s\" port %s "
"(getaddrinfo() error: %s)\n",
address, port ? port : "<null>", gai_strerror(ret));
}
return ret;
}
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);
int sameSocketAddress(struct sockaddr_storage *a, struct sockaddr_storage *b);
int getAddrInfoWithProto(char *address, char *port, int protocol, struct addrinfo **ai);
uint16_t getPort(struct addrinfo* ai);

File diff suppressed because it is too large Load Diff

View File

@@ -31,6 +31,10 @@
result = (EOF == yyc) ? 0 : (*(buf) = yyc, 1); \
}
#define PARSE_ERROR exit(1);
#define MEMORY_ERROR { \
logError("could not allocate memory when parsing configuration.\n"); \
exit(1); \
}
#if defined __clang__
#pragma clang diagnostic ignored "-Wunused-parameter"
@@ -53,7 +57,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;
}
@@ -80,15 +90,15 @@ auth-rule = auth-key - < pattern >
allRules = (Rule *)
realloc(allRules, sizeof(Rule) * (allRulesCount + 1));
if (!allRules) {
PARSE_ERROR;
MEMORY_ERROR;
}
allRules[allRulesCount].pattern = strdup(yytext);
if (!allRules[allRulesCount].pattern) {
PARSE_ERROR;
MEMORY_ERROR;
}
allRules[allRulesCount].type = yy->isAuthAllow ? allowRule : denyRule;
if (seTotal > 0) {
if (seInfo[seTotal - 1].rulesStart == 0) {
if (seInfo[seTotal - 1].rulesStart == 0 && seInfo[seTotal - 1].rulesCount == 0) {
seInfo[seTotal - 1].rulesStart = allRulesCount;
}
++seInfo[seTotal - 1].rulesCount;
@@ -104,7 +114,7 @@ logfile = "logfile" - < filename >
{
logFileName = strdup(yytext);
if (!logFileName) {
PARSE_ERROR;
MEMORY_ERROR;
}
}
@@ -112,7 +122,7 @@ pidlogfile = "pidlogfile" - < filename >
{
pidLogFileName = strdup(yytext);
if (!pidLogFileName) {
PARSE_ERROR;
MEMORY_ERROR;
}
}
@@ -123,7 +133,7 @@ logcommon = "logcommon"
invalid_syntax = < (!eol .)+ > eol
{
fprintf(stderr, "rinetd: invalid syntax at line %d: %s\n",
logError("invalid syntax at line %d: %s\n",
yy->currentLine, yytext);
PARSE_ERROR; /* FIXME */
}
@@ -133,9 +143,10 @@ address = ipv4 | ipv6 | hostname
pattern = (hexdigit | '[' | ']' | ':' | '.' | [*?] )+
number = digit+
ipv4 = number '.' number '.' number '.' number | '0'
ipv6 = (hexdigit | ':')+ | '[' (hexdigit | ':')+ ']'
hostname = (label '.')* name '.'?
ipv4 = number '.' number '.' number '.' number | '0'
ipv6 = '[' bare_ipv6 ']' | bare_ipv6
bare_ipv6 = hexdigit* ':' (hexdigit | ':')* # Must have at least one ':'
hostname = (label '.')* name '.'?
name = id ('-' | id | digit)*
@@ -157,17 +168,18 @@ void parseConfiguration(char const *file)
{
FILE *in = fopen(file, "r");
if (!in) {
PARSE_ERROR;
logError("could not open configuration file %s.\n", file);
exit(1);
}
yycontext ctx;
memset(&ctx, 0, sizeof(yycontext));
ctx.fp = in;
if (!yyparse(&ctx)) {
syslog(LOG_ERR, "invalid syntax "
"on file %s, line %d.\n", file, -1);
logError("invalid syntax in file %s, line %d.\n", file, -1);
exit(1);
}
yyrelease(&ctx);
fclose(in);

View File

@@ -28,9 +28,11 @@
# elif HAVE_SYS_TIME_H
# include <sys/time.h>
# endif
# include <syslog.h>
#endif /* _WIN32 */
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
@@ -106,11 +108,13 @@ enum {
logDenied,
};
RinetdOptions options = {
static RinetdOptions options = {
RINETD_CONFIG_FILE,
0,
};
static int forked = 0;
static void selectPass(void);
static void handleWrite(ConnectionInfo *cnx, Socket *socket, Socket *other_socket);
static void handleRead(ConnectionInfo *cnx, Socket *socket, Socket *other_socket);
@@ -158,15 +162,19 @@ int main(int argc, char *argv[])
readArgs(argc, argv, &options);
if (!options.foreground) {
#if HAVE_DAEMON && !DEBUG
if (!options.foreground && daemon(0, 0) != 0) {
exit(0);
}
if (daemon(0, 0) != 0) {
exit(0);
}
forked = 1;
#elif HAVE_FORK && !DEBUG
if (!options.foreground && fork() != 0) {
exit(0);
}
if (fork() != 0) {
exit(0);
}
forked = 1;
#endif
}
#if HAVE_SIGACTION
struct sigaction act;
@@ -188,7 +196,7 @@ int main(int argc, char *argv[])
registerPID(pidLogFileName ? pidLogFileName : RINETD_PID_FILE);
}
syslog(LOG_INFO, "Starting redirections...\n");
logInfo("starting redirections...\n");
while (1) {
selectPass();
}
@@ -196,6 +204,38 @@ int main(int argc, char *argv[])
return 0;
}
void logError(char const *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
#if !_WIN32
if (forked)
vsyslog(LOG_ERR, fmt, ap);
else
#endif
{
fprintf(stderr, "rinetd error: ");
vfprintf(stderr, fmt, ap);
}
va_end(ap);
}
void logInfo(char const *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
#if !_WIN32
if (forked)
vsyslog(LOG_INFO, fmt, ap);
else
#endif
{
fprintf(stderr, "rinetd: ");
vfprintf(stderr, fmt, ap);
}
va_end(ap);
}
static void clearConfiguration(void) {
/* Remove references to server information */
for (int i = 0; i < coTotal; ++i) {
@@ -250,7 +290,7 @@ static void readConfiguration(char const *file) {
if (logFile) {
setvbuf(logFile, NULL, _IONBF, 0);
} else {
syslog(LOG_ERR, "could not open %s to append (%m).\n",
logError("could not open %s to append (%m).\n",
logFileName);
}
}
@@ -261,93 +301,69 @@ 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 *ai;
int ret = getAddrInfoWithProto(bindAddress, bindPort, bindProtocol, &ai);
if (ret != 0) {
fprintf(stderr, "rinetd: getaddrinfo error: %s\n", gai_strerrorA(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) {
logError("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) {
logError("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. */
logError("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);
ret = getAddrInfoWithProto(connectAddress, connectPort, connectProtocol, &ai);
if (ret != 0) {
fprintf(stderr, "rinetd: getaddrinfo error: %s\n", gai_strerrorA(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);
ret = getAddrInfoWithProto(sourceAddress, NULL, connectProtocol, &ai);
if (ret != 0) {
fprintf(stderr, "rinetd: getaddrinfo error: %s\n", gai_strerrorA(ret));
freeaddrinfo(si.fromAddrInfo);
freeaddrinfo(si.toAddrInfo);
exit(1);
}
si.sourceAddrInfo = servinfo;
si.sourceAddrInfo = ai;
}
#ifndef _WIN32
@@ -432,7 +448,7 @@ static ConnectionInfo *findAvailableConnection(void)
int oldTotal = coTotal;
setConnectionCount(coTotal * 4 / 3 + 8);
if (coTotal == oldTotal) {
syslog(LOG_ERR, "not enough memory to add slots. "
logError("not enough memory to add slots. "
"Currently %d slots.\n", coTotal);
/* Go back to the previous total number of slots */
return NULL;
@@ -669,7 +685,7 @@ static void handleAccept(ServerInfo const *srv)
/* In TCP mode, get remote address using accept(). */
nfd = accept(srv->fd, (struct sockaddr *)&addr, &addrlen);
if (nfd == INVALID_SOCKET) {
syslog(LOG_ERR, "accept(%llu): %m\n", (long long unsigned int)srv->fd);
logError("accept(%llu): %m\n", (long long unsigned int)srv->fd);
logEvent(NULL, srv, logAcceptFailed);
return;
}
@@ -690,7 +706,7 @@ static void handleAccept(ServerInfo const *srv)
if (GetLastError() == WSAEINPROGRESS) {
return;
}
syslog(LOG_ERR, "recvfrom(%llu): %m\n", (long long unsigned int)srv->fd);
logError("recvfrom(%llu): %m\n", (long long unsigned int)srv->fd);
logEvent(NULL, srv, logAcceptFailed);
return;
}
@@ -749,7 +765,7 @@ static void handleAccept(ServerInfo const *srv)
struct addrinfo* to = srv->toAddrInfo;
cnx->local.fd = socket(to->ai_family, to->ai_socktype, to->ai_protocol);
if (cnx->local.fd == INVALID_SOCKET) {
syslog(LOG_ERR, "socket(): %m\n");
logError("socket(): %m\n");
if (cnx->remote.protocol == IPPROTO_TCP)
closesocket(cnx->remote.fd);
cnx->remote.fd = INVALID_SOCKET;
@@ -765,7 +781,7 @@ static void handleAccept(ServerInfo const *srv)
if (srv->sourceAddrInfo) {
if (bind(cnx->local.fd, srv->sourceAddrInfo->ai_addr,
srv->sourceAddrInfo->ai_addrlen) == SOCKET_ERROR) {
syslog(LOG_ERR, "bind(): %m\n");
logError("bind(): %m\n");
}
}
@@ -885,7 +901,7 @@ RETSIGTYPE plumber(int s)
RETSIGTYPE hup(int s)
{
(void)s;
syslog(LOG_INFO, "Received SIGHUP, reloading configuration...\n");
logInfo("received SIGHUP, reloading configuration...\n");
/* Learn the new rules */
clearConfiguration();
readConfiguration(options.conf_file);
@@ -915,8 +931,6 @@ void registerPID(char const *pid_file_name)
FILE *pid_file = fopen(pid_file_name, "w");
if (pid_file == NULL) {
/* non-fatal, non-Linux may lack /var/run... */
fprintf(stderr, "rinetd: Couldn't write to "
"%s. PID was not logged.\n", pid_file_name);
goto error;
} else {
fprintf(pid_file, "%d\n", getpid());
@@ -926,8 +940,8 @@ void registerPID(char const *pid_file_name)
}
return;
error:
syslog(LOG_ERR, "Couldn't write to "
"%s. PID was not logged (%m).\n", pid_file_name);
logError("couldn't write to %s. PID was not logged (%m).\n",
pid_file_name);
#else
/* add other systems with wherever they register processes */
(void)pid_file_name;
@@ -966,7 +980,7 @@ static void logEvent(ConnectionInfo const *cnx, ServerInfo const *srv, int resul
}
if (result==logNotAllowed || result==logDenied)
syslog(LOG_INFO, "%s %s\n"
logInfo("%s %s\n"
, addressText
, logMessages[result]);
if (logFile) {
@@ -1033,7 +1047,7 @@ static int readArgs (int argc, char **argv, RinetdOptions *options)
case 'c':
options->conf_file = optarg;
if (!options->conf_file) {
syslog(LOG_ERR, "Not enough memory to "
fprintf(stderr, "Not enough memory to "
"launch rinetd.\n");
exit(1);
}

View File

@@ -8,17 +8,6 @@
#pragma once
/* Syslog feature */
#if _WIN32
# include <stdio.h>
# define syslog fprintf
# define LOG_ERR stderr
# define LOG_INFO stdout
#else
# include <syslog.h>
#endif /* _WIN32 */
#include <stdint.h>
/* Constants */
@@ -46,6 +35,8 @@ extern FILE *logFile;
/* Functions */
void logError(char const *fmt, ...);
void logInfo(char const *fmt, ...);
void addServer(char *bindAddress, char *bindPort, int bindProtocol,
char *connectAddress, char *connectPort, int connectProtocol,
int serverTimeout, char *sourceAddress);