mirror of
https://github.com/samhocevar/rinetd.git
synced 2025-03-14 20:00:11 +08:00
Allow connecting to remote IPv6 addresses.
This commit is contained in:
parent
b7fcf65a97
commit
79bafee414
75
src/parse.c
75
src/parse.c
@ -20,12 +20,10 @@
|
||||
FILE *fp; \
|
||||
int currentLine; \
|
||||
int isAuthAllow; \
|
||||
char *tmpPort; \
|
||||
uint16_t tmpPortNum, tmpProto; \
|
||||
uint16_t connectPortNum; \
|
||||
int bindProto, connectProto; \
|
||||
char *tmpPort, *bindPort, *connectPort; \
|
||||
int tmpProto, bindProto, connectProto; \
|
||||
int serverTimeout; \
|
||||
char *bindAddress, *bindPort, *connectAddress, *sourceAddress;
|
||||
char *bindAddress, *connectAddress, *sourceAddress;
|
||||
#define YY_INPUT(yyctx, buf, result, max_size) \
|
||||
{ \
|
||||
int yyc = fgetc(yyctx->fp); \
|
||||
@ -358,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 162
|
||||
#line 150
|
||||
++yy->currentLine; ;
|
||||
}
|
||||
#undef yythunkpos
|
||||
@ -372,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 137
|
||||
#line 125
|
||||
|
||||
fprintf(stderr, "rinetd: invalid syntax at line %d: %s\n",
|
||||
yy->currentLine, yytext);
|
||||
@ -390,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 132
|
||||
#line 120
|
||||
|
||||
logFormatCommon = 1;
|
||||
;
|
||||
@ -406,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 124
|
||||
#line 112
|
||||
|
||||
pidLogFileName = strdup(yytext);
|
||||
if (!pidLogFileName) {
|
||||
@ -425,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 116
|
||||
#line 104
|
||||
|
||||
logFileName = strdup(yytext);
|
||||
if (!logFileName) {
|
||||
@ -444,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 113
|
||||
#line 101
|
||||
yy->isAuthAllow = (yytext[0] == 'a'); ;
|
||||
}
|
||||
#undef yythunkpos
|
||||
@ -458,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 91
|
||||
#line 79
|
||||
|
||||
allRules = (Rule *)
|
||||
realloc(allRules, sizeof(Rule) * (allRulesCount + 1));
|
||||
@ -492,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 88
|
||||
#line 76
|
||||
yy->tmpProto = IPPROTO_TCP; ;
|
||||
}
|
||||
#undef yythunkpos
|
||||
@ -506,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 87
|
||||
#line 75
|
||||
yy->tmpProto = IPPROTO_UDP; ;
|
||||
}
|
||||
#undef yythunkpos
|
||||
@ -520,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 86
|
||||
#line 74
|
||||
yy->tmpProto = IPPROTO_TCP; ;
|
||||
}
|
||||
#undef yythunkpos
|
||||
@ -534,36 +532,13 @@ YY_ACTION(void) yy_1_port(yycontext *yy, char *yytext, int yyleng)
|
||||
#define yythunkpos yy->__thunkpos
|
||||
yyprintf((stderr, "do yy_1_port\n"));
|
||||
{
|
||||
#line 85
|
||||
#line 73
|
||||
yy->tmpPort = strdup(yytext); ;
|
||||
}
|
||||
#undef yythunkpos
|
||||
#undef yypos
|
||||
#undef yy
|
||||
}
|
||||
YY_ACTION(void) yy_1_full_port(yycontext *yy, char *yytext, int yyleng)
|
||||
{
|
||||
#define __ yy->__
|
||||
#define yypos yy->__pos
|
||||
#define yythunkpos yy->__thunkpos
|
||||
yyprintf((stderr, "do yy_1_full_port\n"));
|
||||
{
|
||||
#line 74
|
||||
|
||||
char const *proto = yy->tmpProto == IPPROTO_TCP ? "tcp" : "udp";
|
||||
struct servent *service = getservbyname(yy->tmpPort, proto);
|
||||
int port = service ? ntohs(service->s_port) : atoi(yy->tmpPort);
|
||||
if (port <= 0 || port >= 65536) {
|
||||
syslog(LOG_ERR, "port %s/%s missing or out of range\n", yy->tmpPort, proto);
|
||||
PARSE_ERROR;
|
||||
}
|
||||
yy->tmpPortNum = (uint16_t)port;
|
||||
;
|
||||
}
|
||||
#undef yythunkpos
|
||||
#undef yypos
|
||||
#undef yy
|
||||
}
|
||||
YY_ACTION(void) yy_1_option_source(yycontext *yy, char *yytext, int yyleng)
|
||||
{
|
||||
#define __ yy->__
|
||||
@ -571,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 71
|
||||
#line 69
|
||||
yy->sourceAddress = strdup(yytext); ;
|
||||
}
|
||||
#undef yythunkpos
|
||||
@ -585,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 70
|
||||
#line 68
|
||||
yy->serverTimeout = atoi(yytext); ;
|
||||
}
|
||||
#undef yythunkpos
|
||||
@ -599,8 +574,8 @@ 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 65
|
||||
yy->connectPortNum = yy->tmpPortNum; yy->connectProto = yy->tmpProto; ;
|
||||
#line 63
|
||||
yy->connectPort = yy->tmpPort; yy->connectProto = yy->tmpProto; ;
|
||||
}
|
||||
#undef yythunkpos
|
||||
#undef yypos
|
||||
@ -613,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 64
|
||||
#line 62
|
||||
yy->bindPort = yy->tmpPort; yy->bindProto = yy->tmpProto; ;
|
||||
}
|
||||
#undef yythunkpos
|
||||
@ -627,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 63
|
||||
#line 61
|
||||
yy->connectAddress = strdup(yytext); ;
|
||||
}
|
||||
#undef yythunkpos
|
||||
@ -641,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 62
|
||||
#line 60
|
||||
yy->bindAddress = strdup(yytext); ;
|
||||
}
|
||||
#undef yythunkpos
|
||||
@ -655,10 +630,10 @@ YY_ACTION(void) yy_1_server_rule(yycontext *yy, char *yytext, int yyleng)
|
||||
#define yythunkpos yy->__thunkpos
|
||||
yyprintf((stderr, "do yy_1_server_rule\n"));
|
||||
{
|
||||
#line 53
|
||||
#line 51
|
||||
|
||||
addServer(yy->bindAddress, yy->bindPort, yy->bindProto,
|
||||
yy->connectAddress, yy->connectPortNum, yy->connectProto,
|
||||
yy->connectAddress, yy->connectPort, yy->connectProto,
|
||||
yy->serverTimeout > 0 ? yy->serverTimeout : RINETD_DEFAULT_UDP_TIMEOUT,
|
||||
yy->sourceAddress);
|
||||
yy->bindAddress = yy->connectAddress = yy->sourceAddress = NULL;
|
||||
@ -1039,7 +1014,7 @@ YY_RULE(int) yy_option_list(yycontext *yy)
|
||||
}
|
||||
YY_RULE(int) yy_full_port(yycontext *yy)
|
||||
{ int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;
|
||||
yyprintf((stderr, "%s\n", "full_port")); if (!yy_port(yy)) goto l92; if (!yy_proto(yy)) goto l92; yyDo(yy, yy_1_full_port, yy->__begin, yy->__end);
|
||||
yyprintf((stderr, "%s\n", "full_port")); if (!yy_port(yy)) goto l92; if (!yy_proto(yy)) goto l92;
|
||||
yyprintf((stderr, " ok %s @ %s\n", "full_port", yy->__buf+yy->__pos));
|
||||
return 1;
|
||||
l92:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;
|
||||
@ -1415,7 +1390,7 @@ YY_PARSE(yycontext *) YYRELEASE(yycontext *yyctx)
|
||||
}
|
||||
|
||||
#endif
|
||||
#line 166 "parse.peg"
|
||||
#line 154 "parse.peg"
|
||||
|
||||
|
||||
void parseConfiguration(char const *file)
|
||||
|
@ -21,12 +21,10 @@
|
||||
FILE *fp; \
|
||||
int currentLine; \
|
||||
int isAuthAllow; \
|
||||
char *tmpPort; \
|
||||
uint16_t tmpPortNum, tmpProto; \
|
||||
uint16_t connectPortNum; \
|
||||
int bindProto, connectProto; \
|
||||
char *tmpPort, *bindPort, *connectPort; \
|
||||
int tmpProto, bindProto, connectProto; \
|
||||
int serverTimeout; \
|
||||
char *bindAddress, *bindPort, *connectAddress, *sourceAddress;
|
||||
char *bindAddress, *connectAddress, *sourceAddress;
|
||||
#define YY_INPUT(yyctx, buf, result, max_size) \
|
||||
{ \
|
||||
int yyc = fgetc(yyctx->fp); \
|
||||
@ -52,7 +50,7 @@ comment = "#" (!eol .)*
|
||||
server-rule = bind-address - bind-port - connect-address - connect-port (-? server-options)?
|
||||
{
|
||||
addServer(yy->bindAddress, yy->bindPort, yy->bindProto,
|
||||
yy->connectAddress, yy->connectPortNum, yy->connectProto,
|
||||
yy->connectAddress, yy->connectPort, yy->connectProto,
|
||||
yy->serverTimeout > 0 ? yy->serverTimeout : RINETD_DEFAULT_UDP_TIMEOUT,
|
||||
yy->sourceAddress);
|
||||
yy->bindAddress = yy->connectAddress = yy->sourceAddress = NULL;
|
||||
@ -62,7 +60,7 @@ server-rule = bind-address - bind-port - connect-address - connect-port (-? se
|
||||
bind-address = < address > { yy->bindAddress = strdup(yytext); }
|
||||
connect-address = < address > { yy->connectAddress = strdup(yytext); }
|
||||
bind-port = full-port { yy->bindPort = yy->tmpPort; yy->bindProto = yy->tmpProto; }
|
||||
connect-port = full-port { yy->connectPortNum = yy->tmpPortNum; yy->connectProto = yy->tmpProto; }
|
||||
connect-port = full-port { yy->connectPort = yy->tmpPort; yy->connectProto = yy->tmpProto; }
|
||||
server-options = "[" -? option-list -? "]"
|
||||
|
||||
option-list = option (-? ',' -? option-list)?
|
||||
@ -71,16 +69,6 @@ option-timeout = "timeout" -? "=" -? < number > { yy->serverTimeout = atoi(
|
||||
option-source = "src" -? "=" -? < address > { yy->sourceAddress = strdup(yytext); }
|
||||
|
||||
full-port = port proto
|
||||
{
|
||||
char const *proto = yy->tmpProto == IPPROTO_TCP ? "tcp" : "udp";
|
||||
struct servent *service = getservbyname(yy->tmpPort, proto);
|
||||
int port = service ? ntohs(service->s_port) : atoi(yy->tmpPort);
|
||||
if (port <= 0 || port >= 65536) {
|
||||
syslog(LOG_ERR, "port %s/%s missing or out of range\n", yy->tmpPort, proto);
|
||||
PARSE_ERROR;
|
||||
}
|
||||
yy->tmpPortNum = (uint16_t)port;
|
||||
}
|
||||
|
||||
port = < (number | service) > { yy->tmpPort = strdup(yytext); }
|
||||
proto = '/tcp' { yy->tmpProto = IPPROTO_TCP; }
|
||||
|
57
src/rinetd.c
57
src/rinetd.c
@ -212,6 +212,7 @@ static void clearConfiguration(void) {
|
||||
free(srv->fromHost);
|
||||
free(srv->toHost);
|
||||
freeaddrinfo(srv->fromAddrInfo);
|
||||
freeaddrinfo(srv->toAddrInfo);
|
||||
if (srv->sourceAddrInfo) {
|
||||
freeaddrinfo(srv->sourceAddrInfo);
|
||||
}
|
||||
@ -257,14 +258,12 @@ static void readConfiguration(char const *file) {
|
||||
}
|
||||
|
||||
void addServer(char *bindAddress, char *bindPort, int bindProtocol,
|
||||
char *connectAddress, uint16_t connectPort, int connectProtocol,
|
||||
char *connectAddress, char *connectPort, int connectProtocol,
|
||||
int serverTimeout, char *sourceAddress)
|
||||
{
|
||||
ServerInfo si = {
|
||||
.fromHost = bindAddress,
|
||||
.toHost = connectAddress,
|
||||
.toPort = connectPort,
|
||||
.toProtocol = connectProtocol,
|
||||
.serverTimeout = serverTimeout,
|
||||
};
|
||||
|
||||
@ -320,7 +319,22 @@ void addServer(char *bindAddress, char *bindPort, int bindProtocol,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Resolve source address if applicable */
|
||||
/* 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);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "rinetd: getaddrinfo error: %s\n", gai_strerror(ret));
|
||||
freeaddrinfo(si.fromAddrInfo);
|
||||
closesocket(si.fd);
|
||||
exit(1);
|
||||
}
|
||||
si.toAddrInfo = servinfo;
|
||||
|
||||
/* Resolve source address if applicable. */
|
||||
if (sourceAddress) {
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC,
|
||||
@ -330,20 +344,13 @@ void addServer(char *bindAddress, char *bindPort, int bindProtocol,
|
||||
ret = getaddrinfo(sourceAddress, NULL, &hints, &servinfo);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "rinetd: getaddrinfo error: %s\n", gai_strerror(ret));
|
||||
freeaddrinfo(si.fromAddrInfo);
|
||||
freeaddrinfo(si.toAddrInfo);
|
||||
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",
|
||||
bindAddress);
|
||||
closesocket(si.fd);
|
||||
exit(1);
|
||||
}
|
||||
si.localPort = htons(connectPort);
|
||||
|
||||
#ifndef _WIN32
|
||||
if (si.fd > maxfd) {
|
||||
maxfd = si.fd;
|
||||
@ -711,7 +718,7 @@ static void handleAccept(ServerInfo const *srv)
|
||||
}
|
||||
|
||||
cnx->local.fd = INVALID_SOCKET;
|
||||
cnx->local.protocol = srv->toProtocol;
|
||||
cnx->local.protocol = srv->toAddrInfo->ai_protocol;
|
||||
cnx->local.recvPos = cnx->local.sentPos = 0;
|
||||
cnx->local.totalBytesIn = cnx->local.totalBytesOut = 0;
|
||||
|
||||
@ -741,9 +748,8 @@ static void handleAccept(ServerInfo const *srv)
|
||||
/* Now open a connection to the local server.
|
||||
This, too, is nonblocking. Why wait
|
||||
for anything when you don't have to? */
|
||||
struct sockaddr_in saddr;
|
||||
/* FIXME: don’t forget to switch to PF_INET6 for IPv6. */
|
||||
cnx->local.fd = socket(PF_INET, getSocketType(srv->toProtocol), srv->toProtocol);
|
||||
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");
|
||||
if (cnx->remote.protocol == IPPROTO_TCP)
|
||||
@ -753,7 +759,7 @@ static void handleAccept(ServerInfo const *srv)
|
||||
return;
|
||||
}
|
||||
|
||||
if (srv->toProtocol == IPPROTO_TCP)
|
||||
if (srv->toAddrInfo->ai_protocol == IPPROTO_TCP)
|
||||
setSocketDefaults(cnx->local.fd);
|
||||
|
||||
/* Bind the local socket even though we use connect() later, so that
|
||||
@ -765,12 +771,8 @@ static void handleAccept(ServerInfo const *srv)
|
||||
}
|
||||
}
|
||||
|
||||
memset(&saddr, 0, sizeof(struct sockaddr_in));
|
||||
saddr.sin_family = AF_INET;
|
||||
memcpy(&saddr.sin_addr, &srv->localAddr, sizeof(struct in_addr));
|
||||
saddr.sin_port = srv->localPort;
|
||||
if (connect(cnx->local.fd, (struct sockaddr *)&saddr,
|
||||
sizeof(struct sockaddr_in)) == SOCKET_ERROR)
|
||||
if (connect(cnx->local.fd, srv->toAddrInfo->ai_addr,
|
||||
srv->toAddrInfo->ai_addrlen) == SOCKET_ERROR)
|
||||
{
|
||||
if ((GetLastError() != WSAEINPROGRESS) &&
|
||||
(GetLastError() != WSAEWOULDBLOCK))
|
||||
@ -787,10 +789,9 @@ static void handleAccept(ServerInfo const *srv)
|
||||
}
|
||||
|
||||
/* Send a zero-size UDP packet to simulate a connection */
|
||||
if (srv->toProtocol == IPPROTO_UDP) {
|
||||
if (srv->toAddrInfo->ai_protocol == IPPROTO_UDP) {
|
||||
int got = sendto(cnx->local.fd, NULL, 0, 0,
|
||||
(struct sockaddr const *)&saddr,
|
||||
(SOCKLEN_T)sizeof(saddr));
|
||||
srv->toAddrInfo->ai_addr, srv->toAddrInfo->ai_addrlen);
|
||||
/* FIXME: we ignore errors here... is it safe? */
|
||||
(void)got;
|
||||
}
|
||||
@ -1012,7 +1013,7 @@ static void logEvent(ConnectionInfo const *cnx, ServerInfo const *srv, int resul
|
||||
fromHost = srv->fromHost;
|
||||
fromPort = getPort(srv->fromAddrInfo);
|
||||
toHost = srv->toHost;
|
||||
toPort = srv->toPort;
|
||||
toPort = getPort(srv->toAddrInfo);
|
||||
}
|
||||
|
||||
if (result==logNotAllowed || result==logDenied)
|
||||
|
@ -47,6 +47,5 @@ extern FILE *logFile;
|
||||
/* Functions */
|
||||
|
||||
void addServer(char *bindAddress, char *bindPort, int bindProtocol,
|
||||
char *connectAddress, uint16_t connectPort, int connectProtocol,
|
||||
char *connectAddress, char *connectPort, int connectProtocol,
|
||||
int serverTimeout, char *sourceAddress);
|
||||
|
||||
|
@ -29,15 +29,10 @@ struct _server_info {
|
||||
SOCKET fd;
|
||||
|
||||
/* In network order, for network purposes */
|
||||
struct in_addr localAddr;
|
||||
uint16_t localPort;
|
||||
struct addrinfo *sourceAddrInfo;
|
||||
struct addrinfo *fromAddrInfo, *toAddrInfo, *sourceAddrInfo;
|
||||
|
||||
/* In ASCII and local byte order, for logging purposes */
|
||||
/* In ASCII, for logging purposes */
|
||||
char *fromHost, *toHost;
|
||||
struct addrinfo *fromAddrInfo;
|
||||
int16_t toPort;
|
||||
int toProtocol;
|
||||
|
||||
/* Offset and count into list of allow and deny rules. Any rules
|
||||
prior to globalAllowRules and globalDenyRules are global rules. */
|
||||
|
Loading…
Reference in New Issue
Block a user