Allow connecting to remote IPv6 addresses.

This commit is contained in:
Sam Hocevar 2021-02-14 09:04:08 +01:00
parent b7fcf65a97
commit 79bafee414
5 changed files with 62 additions and 104 deletions

View File

@ -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)

View 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; }

View File

@ -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: dont 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)

View File

@ -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);

View File

@ -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. */