Fixing a compilation issue, wherein two global vars, conf and chan, were defined...
[revinetd.git] / revinetd.c
blob9c15da6f158f0b38c01f2d156066023ecb8d022e
1 /*
2 * revinetd.c
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,
22 * USA.
24 * */
26 #include "includes.h"
27 #include "revinetd.h"
28 #include "relay_agt.h"
29 #include "server.h"
30 #include "misc.h"
32 /* Global variable. */
33 Conf conf;
34 char *exec_name;
36 static const char cvsid[] = "$Id: revinetd.c,v 1.29 2008/08/28 03:24:59 necrotaur Exp, adapted by ThP $";
38 int
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
43 segfaults. */
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'},
58 {0, 0, 0, 0}};
59 /* getopt_long stores the option index here. */
60 int c, option_index = 0;
61 pid_t pid;
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);
68 init_conf();
70 while (1) {
71 c = getopt_long(argc, argv, "hdrsc:l:b:t:qvk:L:", long_options,
72 &option_index);
74 /* Detect the end of the options. */
75 if (c == -1)
76 break;
78 switch (c) {
79 case 0:
80 /* If this option set a flag, do nothing else now. */
81 if (long_options[option_index].flag != 0)
82 break;
83 printf("option %s", long_options[option_index].name);
84 if (optarg)
85 printf(" with arg %s", optarg);
86 printf("\n");
87 break;
89 case 'd':
90 conf.daemonize = 1;
91 conf.verbosity = VB_QUIET;
92 break;
94 case 's':
95 if (conf.server_flag == FLAG_NONE) {
96 conf.server_flag = FLAG_SERVER;
97 } else {
98 fprintf(stderr, "You can only set one mode, either Server or "
99 "Relay Agent, not both.\n\n");
100 usage();
102 break;
104 case 'r':
105 if (conf.server_flag == FLAG_NONE) {
106 conf.server_flag = FLAG_RELAY;
107 } else {
108 fprintf(stderr, "You can only set one mode, either Server or "
109 "Relay Agent, not both.\n\n");
110 usage();
112 break;
114 case 'c':
115 if (conf.server_flag == FLAG_SERVER) {
116 conf.host = strdup(optarg);
117 conf.port = parse_host_str(conf.host);
118 } else {
119 fprintf(stderr, "You must select Server mode to use -c or "
120 "--listen-client.\n\n");
121 usage();
123 break;
125 case 'l':
126 if (conf.server_flag == FLAG_SERVER) {
127 conf.host2 = strdup(optarg);
128 conf.port2 = parse_host_str(conf.host2);
129 } else {
130 fprintf(stderr, "You must select Server mode to use -l or "
131 "--listen-relay.\n\n");
132 usage();
134 break;
136 case 'b':
137 if (conf.server_flag == FLAG_RELAY) {
138 conf.host = strdup(optarg);
139 conf.port = parse_host_str(conf.host);
140 } else {
141 fprintf(stderr, "You must select Relay Agent mode to use -c "
142 "or --server-host.\n\n");
143 usage();
145 break;
147 case 't':
148 if (conf.server_flag == FLAG_RELAY) {
149 conf.host2 = strdup(optarg);
150 conf.port2 = parse_host_str(conf.host2);
151 } else {
152 fprintf(stderr, "You must select Relay Agent mode to use -t "
153 "or --target-host.\n\n");
154 usage();
156 break;
157 case 'h':
158 usage();
159 break;
161 case 'k':
162 conf.keepalive = atoi(optarg);
163 break;
165 case 'L':
166 conf.access_log_filepath = strdup(optarg);
167 break;
169 case 'v':
170 if (conf.daemonize == 0) {
171 //conf.verbosity = VB_VERBOSE;
172 conf.verbosity++;
174 break;
176 case 'q':
177 conf.verbosity = VB_QUIET;
178 break;
180 case '?':
181 /* FALL THROUGH */
182 default:
183 usage();
187 /* Print any remaining command line arguments (not options). */
188 if (optind < argc) {
189 usage();
192 if (conf.daemonize == TRUE) {
193 pid = fork();
195 if (pid > 0) { /* parent */
196 exit(0);
197 } else if (pid < 0) { /* error */
198 perror("fork");
199 exit(1);
200 } /* child */
201 setsid();
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);
214 } else {
215 fprintf(stderr, "Two ports, port1 (-c and --client-port) and "
216 "port2 (-l and --ra-port) must be "
217 "provided.\n\n");
218 usage();
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);
223 } else {
224 fprintf(stderr, "Both a server (-b and --server-host) and a "
225 "target (-t and --target-host)\nmust be "
226 "specified.\n\n");
227 usage();
229 } else {
230 usage();
233 clean_exit(SIGQUIT);
236 void
237 usage(void)
240 fprintf(stderr, "Usage: revinetd -s -c HOST1:PORT1 -l HOST2:PORT2 [-d]"
241 "\n"
242 " revinetd -r -b HOST1:PORT1 -t "
243 "HOST2:PORT2 [-d] [-k seconds]\n"
244 "\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"
253 "\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 "
260 "host and port\n"
261 " -t HOST2:PORT2 --target-host=HOST2:PORT2\tThe target host "
262 "and port\n\n"
263 " optional arguments:\n"
264 " -k seconds --keep-alive=seconds\tKeep-alive signal interval\n"
265 " \tdefaults to 180 seconds\n\n");
267 clean_exit(SIGQUIT);
270 void
271 clean_exit(int sig)
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) {
279 perror("shutdown");
281 close(open_sock->sock);
282 open_sock = open_sock->next;
285 if (conf.access_log_file != NULL)
286 fclose(conf.access_log_file);
288 exit(0);
291 // Adapted to search for the colon from the right. (thpi)
292 unsigned short
293 parse_host_str(char *host_str)
295 unsigned short port;
296 int j;
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;
304 if (j < 0) return 0;
305 while (*(host_str + j) != ':') {
306 if (isspace(*(host_str + j))) {
307 *(host_str + j) = '\0'; // remove the trailing padding
309 --j;
310 if (j < 0) {
311 fprintf(stderr, "Invalid hostname format.\n");
312 usage();
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';
320 /* Grab the port. */
321 port = (unsigned short)atoi(host_str + j);
323 return port;
326 void
327 init_conf(void)
330 memset(&conf, 0, sizeof(Conf));
331 conf.port = -1;
332 conf.port2 = -1;
333 conf.verbosity = VB_NORMAL;
334 conf.keepalive = 180L;
335 conf.access_log_filepath = "";
336 conf.access_log_file = NULL;