mirror of
https://github.com/samhocevar/rinetd.git
synced 2026-08-21 22:03:28 +08:00
Compare commits
18 Commits
feature-ip
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4e0a60119 | ||
|
|
af88e6fd4f | ||
|
|
ff41723590 | ||
|
|
d3dd35327f | ||
|
|
49bf544bad | ||
|
|
1060048fe8 | ||
|
|
e3b47d086a | ||
|
|
f91e34c3af | ||
|
|
5e8be95d8a | ||
|
|
7887c17096 | ||
|
|
432aa4d230 | ||
|
|
b00f175fa4 | ||
|
|
6a1e7e75a3 | ||
|
|
7f76652af9 | ||
|
|
bb0d64ed5d | ||
|
|
3b33f45925 | ||
|
|
878c804d32 | ||
|
|
f9f5aeda80 |
22
CHANGES.md
22
CHANGES.md
@@ -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
|
||||
|
||||
@@ -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 don’t have a testsuite yet.
|
||||
test:
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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
|
||||
|
||||
12
rinetd.8
12
rinetd.8
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
20
src/net.c
20
src/net.c
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
605
src/parse.c
605
src/parse.c
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
|
||||
182
src/rinetd.c
182
src/rinetd.c
@@ -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);
|
||||
}
|
||||
|
||||
13
src/rinetd.h
13
src/rinetd.h
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user