4 * This file is a part of the revinetd project
6 * Revinetd is copyright (c) 2003-2008 by Steven M. Gill
7 * and distributed under the GPL.
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
28 #include "relay_agt.h"
32 /* Global variable. */
36 static const char cvsid
[] = "$Id: revinetd.c,v 1.29 2008/08/28 03:24:59 necrotaur Exp, adapted by ThP $";
39 main(int argc
, char **argv
)
41 /* All variables are initialized to a known invalid value so that they
42 are not used un-initialized. To use them should trip tests or cause
44 static struct option long_options
[] = {
45 /* These options set a flag. */
46 {"help", no_argument
, 0, 'h'},
47 {"daemonize", no_argument
, 0, 'd'},
48 {"relay-agent", no_argument
, 0, 'r'},
49 {"server", no_argument
, 0, 's'},
50 {"listen-client", required_argument
, 0, 'c'},
51 {"listen-relay", required_argument
, 0, 'l'},
52 {"server-host", required_argument
, 0, 'b'},
53 {"target-host", required_argument
, 0, 't'},
54 {"verbose", no_argument
, 0, 'v'},
55 {"quiet", no_argument
, 0, 'q'},
56 {"keep-alive", required_argument
, 0, 'k'},
57 {"access-log", required_argument
, 0, 'L'},
59 /* getopt_long stores the option index here. */
60 int c
, option_index
= 0;
63 printf("%s - v1.0.2_p6b_20211226 - Copyright (c) 2003-2008 Steven M. Gill, et al (201x, 2020)\n", *argv
);
64 printf("%s is distributed under the terms of the GPL\n", *argv
);
65 printf("http://revinetd.sourceforge.net\n\n");
66 exec_name
= strdup(*argv
);
71 c
= getopt_long(argc
, argv
, "hdrsc:l:b:t:qvk:L:", long_options
,
74 /* Detect the end of the options. */
80 /* If this option set a flag, do nothing else now. */
81 if (long_options
[option_index
].flag
!= 0)
83 printf("option %s", long_options
[option_index
].name
);
85 printf(" with arg %s", optarg
);
91 conf
.verbosity
= VB_QUIET
;
95 if (conf
.server_flag
== FLAG_NONE
) {
96 conf
.server_flag
= FLAG_SERVER
;
98 fprintf(stderr
, "You can only set one mode, either Server or "
99 "Relay Agent, not both.\n\n");
105 if (conf
.server_flag
== FLAG_NONE
) {
106 conf
.server_flag
= FLAG_RELAY
;
108 fprintf(stderr
, "You can only set one mode, either Server or "
109 "Relay Agent, not both.\n\n");
115 if (conf
.server_flag
== FLAG_SERVER
) {
116 conf
.host
= strdup(optarg
);
117 conf
.port
= parse_host_str(conf
.host
);
119 fprintf(stderr
, "You must select Server mode to use -c or "
120 "--listen-client.\n\n");
126 if (conf
.server_flag
== FLAG_SERVER
) {
127 conf
.host2
= strdup(optarg
);
128 conf
.port2
= parse_host_str(conf
.host2
);
130 fprintf(stderr
, "You must select Server mode to use -l or "
131 "--listen-relay.\n\n");
137 if (conf
.server_flag
== FLAG_RELAY
) {
138 conf
.host
= strdup(optarg
);
139 conf
.port
= parse_host_str(conf
.host
);
141 fprintf(stderr
, "You must select Relay Agent mode to use -c "
142 "or --server-host.\n\n");
148 if (conf
.server_flag
== FLAG_RELAY
) {
149 conf
.host2
= strdup(optarg
);
150 conf
.port2
= parse_host_str(conf
.host2
);
152 fprintf(stderr
, "You must select Relay Agent mode to use -t "
153 "or --target-host.\n\n");
162 conf
.keepalive
= atoi(optarg
);
166 conf
.access_log_filepath
= strdup(optarg
);
170 if (conf
.daemonize
== 0) {
171 //conf.verbosity = VB_VERBOSE;
177 conf
.verbosity
= VB_QUIET
;
187 /* Print any remaining command line arguments (not options). */
192 if (conf
.daemonize
== TRUE
) {
195 if (pid
> 0) { /* parent */
197 } else if (pid
< 0) { /* error */
203 close(0); close(1); close(2);
206 signal(SIGTERM
, clean_exit
);
207 signal(SIGINT
, clean_exit
);
208 signal(SIGQUIT
, clean_exit
);
209 signal(SIGHUP
, clean_exit
);
211 if (conf
.server_flag
== FLAG_SERVER
) {
212 if (conf
.port
>= 0 && conf
.port2
>= 0) {
213 server(conf
.host
, conf
.port
, conf
.host2
, conf
.port2
);
215 fprintf(stderr
, "Two ports, port1 (-c and --client-port) and "
216 "port2 (-l and --ra-port) must be "
220 } else if (conf
.server_flag
== FLAG_RELAY
) {
221 if (conf
.host
!= NULL
&& conf
.host2
!= NULL
) {
222 relay_agent(conf
.host
, conf
.port
, conf
.host2
, conf
.port2
);
224 fprintf(stderr
, "Both a server (-b and --server-host) and a "
225 "target (-t and --target-host)\nmust be "
240 fprintf(stderr
, "Usage: revinetd -s -c HOST1:PORT1 -l HOST2:PORT2 [-d]"
242 " revinetd -r -b HOST1:PORT1 -t "
243 "HOST2:PORT2 [-d] [-k seconds]\n"
245 "Global arguments:\n"
246 " -s --server\t\tRuns in server mode\n"
247 " -r --relay-agent\tRuns as the relay agent\n"
248 " -d --daemonize\tRuns as a daemon (implies -q)\n"
249 " -L logfile\t\tLog accesses on client-side (of server) to logfile\n"
250 " -h --help\t\tPrints this message and exit\n"
251 " -q --quiet\t\tSurpress all messages\n"
252 " -v --verbose\t\tIncrease verbiosity\n"
254 "Server arguments:\n"
255 " -c HOST1:PORT1 --client-port=HOST1:PORT1\tListen for a client on IP and Port\n"
256 " -l HOST2:PORT2 --ra-port=HOST2:PORT2 \tListen for a relay agent on IP and Port\n"
257 "Relay agent arguments:\n"
258 " required arguments:\n"
259 " -b HOST1:PORT1 --server-host=HOST1:PORT1\tRevinetd server "
261 " -t HOST2:PORT2 --target-host=HOST2:PORT2\tThe target host "
263 " optional arguments:\n"
264 " -k seconds --keep-alive=seconds\tKeep-alive signal interval\n"
265 " \tdefaults to 180 seconds\n\n");
273 OpenSockets
*open_sock
;
275 /* Close all registered sockets. */
276 open_sock
= conf
.open_sock
;
277 while (open_sock
!= NULL
) {
278 if (shutdown(open_sock
->sock
, SHUT_RDWR
) == -1) {
281 close(open_sock
->sock
);
282 open_sock
= open_sock
->next
;
285 if (conf
.access_log_file
!= NULL
)
286 fclose(conf
.access_log_file
);
291 // Adapted to search for the colon from the right. (thpi)
293 parse_host_str(char *host_str
)
298 /* Skip any leading spaces. */
299 while (isspace(*host_str
)) { host_str
++; }
301 /* Loop through the line until we reach a ':'. Exit with errors if we
302 stumble on an illegal character. */
303 j
= strlen(host_str
)-1;
305 while (*(host_str
+ j
) != ':') {
306 if (isspace(*(host_str
+ j
))) {
307 *(host_str
+ j
) = '\0'; // remove the trailing padding
311 fprintf(stderr
, "Invalid hostname format.\n");
316 /* Insert a NUL byte at the position of the right-most ':' to delimitate the
317 hostname. And then skip ahead one byte. */
318 *(host_str
+ j
++) = '\0';
321 port
= (unsigned short)atoi(host_str
+ j
);
330 memset(&conf
, 0, sizeof(Conf
));
333 conf
.verbosity
= VB_NORMAL
;
334 conf
.keepalive
= 180L;
335 conf
.access_log_filepath
= "";
336 conf
.access_log_file
= NULL
;