1 #define VERSION "0.62"
2 #define LINUX
3
4 #ifdef WIN32
5 #include <windows.h>
6 #include <winsock.h>
7 #include "getopt.h"
8 #else
9 #include <arpa/inet.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <sys/ioctl.h>
13 #include <netdb.h>
14 #include <netinet/in.h>
15 #include <getopt.h>
16 #include <errno.h>
17 #define INVALID_SOCKET (-1)
18 #include <sys/time.h>
19 #endif /* WIN32 */
20
21 #include <unistd.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <signal.h>
25 #include <stdlib.h>
26 #include <fcntl.h>
27 #include <time.h>
28 #include <ctype.h>
29
30 #ifndef WIN32
31 /* Windows sockets compatibility defines */
32 #define INVALID_SOCKET (-1)
33 #define SOCKET_ERROR (-1)
34 int closesocket(int s);
35
36 int closesocket(int s) {
37 return close(s);
38 }
39 #define ioctlsocket ioctl
40 #define MAKEWORD(a, b)
41 #define WSAStartup(a, b) (0)
42 #define WSACleanup()
43 #ifdef __MAC__
44 /* The constants for these are a little screwy in the prelinked
45 MSL GUSI lib and we can't rebuild it, so roll with it */
46 #define WSAEWOULDBLOCK EWOULDBLOCK
47 #define WSAEAGAIN EAGAIN
48 #define WSAEINPROGRESS EINPROGRESS
49 #else
50 #define WSAEWOULDBLOCK EWOULDBLOCK
51 #define WSAEAGAIN EAGAIN
52 #define WSAEINPROGRESS EINPROGRESS
53 #endif /* __MAC__ */
54 #define WSAEINTR EINTR
55 #define SOCKET int
56 #define GetLastError() (errno)
57 typedef struct {
58 int dummy;
59 } WSADATA;
60
61 void Sleep(long ms);
62
63 void Sleep(long ms)
64 {
65 struct timeval tv;
66 tv.tv_sec = ms / 1000;
67 tv.tv_usec = ms * 1000;
68 select(0, 0, 0, 0, &tv);
69 }
70 #else
71 /* WIN32 doesn't really have WSAEAGAIN */
72 #ifndef WSAEAGAIN
73 #define WSAEAGAIN WSAEWOULDBLOCK
74 #endif
75 #endif /* WIN32 */
76
77 #ifndef TRUE
78 #define TRUE 1
79 #endif
80
81 #ifndef FALSE
82 #define FALSE 0
83 #endif
84
85 #ifdef DEBUG
86 #define PERROR perror
87 #else
88 #define PERROR(x)
89 #endif /* DEBUG */
90
91 /* We've got to get FIONBIO from somewhere. Try the Solaris location
92 if it isn't defined yet by the above includes. */
93 #ifndef FIONBIO
94 #include <sys/filio.h>
95 #endif /* FIONBIO */
96
97 #include "match.h"
98
99 SOCKET *seFds = 0;
100 /* In network order, for network purposes */
101 struct in_addr *seLocalAddrs = 0;
102 unsigned short *seLocalPorts = 0;
103 /* In ASCII and local byte order, for logging purposes */
104 char **seFromHosts;
105 int *seFromPorts;
106 char **seToHosts;
107 int *seToPorts;
108
109 /* Offsets into list of allow and deny rules. Any rules
110 prior to globalAllowRules and globalDenyRules are global rules. */
111
112 int *seAllowRules = 0;
113 int *seAllowRulesTotal = 0;
114 int globalAllowRules = 0;
115 int *seDenyRules = 0;
116 int *seDenyRulesTotal = 0;
117 int globalDenyRules = 0;
118
119 SOCKET *reFds = 0;
120 SOCKET *loFds = 0;
121 unsigned char *reAddresses = 0;
122 int *coInputRPos = 0;
123 int *coInputWPos = 0;
124 int *coOutputRPos = 0;
125 int *coOutputWPos = 0;
126 int *coClosed = 0;
127 int *coClosing = 0;
128 int *reClosed = 0;
129 int *loClosed = 0;
130 int *coBytesInput = 0;
131 int *coBytesOutput = 0;
132 int *coLog = 0;
133 int *coSe = 0;
134 char **coInput = 0;
135 char **coOutput = 0;
136 char **allowRules = 0;
137 char **denyRules = 0;
138 int *denyRulesFor = 0;
139 int seTotal = 0;
140 int coTotal = 0;
141 int allowRulesTotal = 0;
142 int denyRulesTotal = 0;
143 int maxfd = 0;
144 char *logFileName = 0;
145 char *pidLogFileName = 0;
146 int logFormatCommon = 0;
147 FILE *logFile = 0;
148
149 /* If 'newsize' bytes can be allocated, *data is set to point
150 to them, the previous data is copied, and 1 is returned.
151 If 'size' bytes cannot be allocated, *data is UNCHANGED,
152 and 0 is returned. */
153
154 #define SAFE_REALLOC(x, y, z) safeRealloc((void **) (x), (y), (z))
155
156 int safeRealloc(void **data, int oldsize, int newsize);
157
158 /*
159 se: (se)rver sockets
160 re: (re)mote sockets
161 lo: (lo)cal sockets (being redirected to)
162 co: connections
163 */
164
165 #define bufferSpace 1024
166
167 void readConfiguration();
168
169 /* Signal handlers */
170 void plumber(int s);
171 void hup(int s);
172 void term(int s);
173
174 void initArrays(void);
175 void RegisterPID(void);
176
177 void selectLoop(void);
178
179 void local_log(int i, int coSe, int result);
180
181 int getAddress(char *host, struct in_addr *iaddr);
182
183 char *logMessages[] = {
184 "done-local-closed",
185 "done-remote-closed",
186 "accept-failed -",
187 0,
188 "local-socket-failed -",
189 0,
190 "local-bind-failed -",
191 0,
192 "local-connect-failed -",
193 0,
194 "not-allowed",
195 0,
196 "denied",
197 0
198 };
199
200 #define logDone 0
201 #define logAcceptFailed 2
202 #define logLocalSocketFailed 4
203 #define logLocalBindFailed 6
204 #define logLocalConnectFailed 8
205 #define logNotAllowed 10
206 #define logDenied 12
207
208 #define logLocalClosedFirst 0
209 #define logRemoteClosedFirst 1
210
211 /* Option parsing */
212
213 typedef struct _rinetd_options RinetdOptions;
214 struct _rinetd_options
215 {
216 char *conf_file;
217 };
218
219 RinetdOptions options = {
220 "/etc/rinetd.conf"
221 };
222
223 int readArgs (int argc,
224 char **argv,
225 RinetdOptions *options);
226
227 int main(int argc, char *argv[])
228 {
229 //WSADATA wsaData;
230 int result = WSAStartup(MAKEWORD(1, 1), &wsaData);
231 if (result != 0) {
232 fprintf(stderr, "Your computer was not connected "
233 "to the Internet at the time that "
234 "this program was launched, or you "
235 "do not have a 32-bit "
236 "connection to the Internet.");
237 exit(1);
238 }
239 readArgs(argc, argv, &options);
240 #ifndef WIN32
241 #ifndef DEBUG
242 if (!fork()) {
243 if (!fork()) {
244 #endif /* DEBUG */
245 signal(SIGPIPE, plumber);
246 signal(SIGHUP, hup);
247 #endif /* WIN32 */
248 signal(SIGTERM, term);
249 initArrays();
250 readConfiguration();
251 RegisterPID();
252 selectLoop();
253 #ifndef WIN32
254 #ifndef DEBUG
255 } else {
256 exit(0);
257 }
258 } else {
259 exit(0);
260 }
261 #endif /* DEBUG */
262 #endif /* WIN32 */
263 return 0;
264 }
265
266 int getConfLine(FILE *in, char *line, int space, int *lnum);
267
268 int patternBad(char *pattern);
269
270 void readConfiguration(void)
271 {
272 FILE *in;
273 char line[16384];
274 int lnum = 0;
275 int i;
276 int ai;
277 int di;
278 if (seFds) {
279 /* Close existing server sockets. */
280 for (i = 0; (i < seTotal); i++) {
281 if (seFds[i] != -1) {
282 closesocket(seFds[i]);
283 free(seFromHosts[i]);
284 free(seToHosts[i]);
285 }
286 }
287 /* Free memory associated with previous set. */
288 free(seFds);
289 free(seLocalAddrs);
290 free(seLocalPorts);
291 free(seFromHosts);
292 free(seFromPorts);
293 free(seToHosts);
294 free(seToPorts);
295 free(seAllowRules);
296 free(seDenyRules);
297 free(seAllowRulesTotal);
298 free(seDenyRulesTotal);
299 }
300 seTotal = 0;
301 if (allowRules) {
302 /* Forget existing allow rules. */
303 for (i = 0; (i < allowRulesTotal); i++) {
304 free(allowRules[i]);
305 }
306 /* Free memory associated with previous set. */
307 free(allowRules);
308 globalAllowRules = 0;
309 }
310 allowRulesTotal = 0;
311 if (denyRules) {
312 /* Forget existing deny rules. */
313 for (i = 0; (i < denyRulesTotal); i++) {
314 free(denyRules[i]);
315 }
316 /* Free memory associated with previous set. */
317 free(denyRules);
318 globalDenyRules = 0;
319 }
320 denyRulesTotal = 0;
321 if (logFileName) {
322 free(logFileName);
323 logFileName = 0;
324 }
325 if (pidLogFileName) {
326 free(pidLogFileName);
327 pidLogFileName = 0;
328 }
329 /* 1. Count the non-comment lines of each type and
330 allocate space for the data. */
331 in = fopen(options.conf_file, "r");
332 if (!in) {
333 fprintf(stderr, "rinetd: can't open %s\n", options.conf_file);
334 exit(1);
335 }
336 while (1) {
337 char *t = 0;
338 if (!getConfLine(in, line, sizeof(line), &lnum)) {
339 break;
340 }
341 t = strtok(line, " \t\r\n");
342 if (!strcmp(t, "logfile")) {
343 continue;
344 } else if (!strcmp(t, "pidlogfile")) {
345 continue;
346 } else if (!strcmp(t, "logcommon")) {
347 continue;
348 } else if (!strcmp(t, "allow")) {
349 allowRulesTotal++;
350 } else if (!strcmp(t, "deny")) {
351 denyRulesTotal++;
352 } else {
353 /* A regular forwarding rule */
354 seTotal++;
355 }
356 }
357 fclose(in);
358 seFds = (SOCKET *) malloc(sizeof(int) * seTotal);
359 if (!seFds) {
360 goto lowMemory;
361 }
362 seLocalAddrs = (struct in_addr *) malloc(sizeof(struct in_addr) *
363 seTotal);
364 if (!seLocalAddrs) {
365 goto lowMemory;
366 }
367 seLocalPorts = (unsigned short *)
368 malloc(sizeof(unsigned short) * seTotal);
369 if (!seLocalPorts) {
370 goto lowMemory;
371 }
372 seFromHosts = (char **)
373 malloc(sizeof(char *) * seTotal);
374 if (!seFromHosts) {
375 goto lowMemory;
376 }
377 seFromPorts = (int *)
378 malloc(sizeof(int) * seTotal);
379 if (!seFromPorts) {
380 goto lowMemory;
381 }
382 seToHosts = (char **)
383 malloc(sizeof(char *) * seTotal);
384 if (!seToHosts) {
385 goto lowMemory;
386 }
387 seToPorts = (int *)
388 malloc(sizeof(int) * seTotal);
389 if (!seToPorts) {
390 goto lowMemory;
391 }
392 allowRules = (char **)
393 malloc(sizeof(char *) * allowRulesTotal);
394 if (!allowRules) {
395 goto lowMemory;
396 }
397 denyRules = (char **)
398 malloc(sizeof(char *) * denyRulesTotal);
399 if (!denyRules) {
400 goto lowMemory;
401 }
402 seAllowRules = (int *)
403 malloc(sizeof(int) * seTotal);
404 if (!seAllowRules) {
405 goto lowMemory;
406 }
407 seAllowRulesTotal = (int *)
408 malloc(sizeof(int) * seTotal);
409 if (!seAllowRulesTotal) {
410 goto lowMemory;
411 }
412 seDenyRules = (int *)
413 malloc(sizeof(int) * seTotal);
414 if (!seDenyRules) {
415 goto lowMemory;
416 }
417 seDenyRulesTotal = (int *)
418 malloc(sizeof(int) * seTotal);
419 if (!seDenyRulesTotal) {
420 goto lowMemory;
421 }
422 /* 2. Make a second pass to configure them. */
423 i = 0;
424 ai = 0;
425 di = 0;
426 lnum = 0;
427 in = fopen(options.conf_file, "r");
428 if (!in) {
429 goto lowMemory;
430 }
431 if (seTotal > 0) {
432 seAllowRulesTotal[i] = 0;
433 seDenyRulesTotal[i] = 0;
434 }
435 while (1) {
436 char *bindAddress;
437 unsigned short bindPort;
438 char *connectAddress;
439 char *bindPortS;
440 char *connectPortS;
441 unsigned short connectPort;
442 struct in_addr iaddr;
443 struct sockaddr_in saddr;
444 struct servent *service;
445 int j;
446 if (!getConfLine(in, line, sizeof(line), &lnum)) {
447 break;
448 }
449 bindAddress = strtok(line, " \t\r\n");
450 if (!bindAddress) {
451 fprintf(stderr, "rinetd: no bind address specified "
452 "on line %d.\n", lnum);
453 continue;
454 }
455 if (!strcmp(bindAddress, "allow")) {
456 char *pattern = strtok(0, " \t\r\n");
457 if (!pattern) {
458 fprintf(stderr, "rinetd: nothing to allow "
459 "specified on line %d.\n", lnum);
460 continue;
461 }
462 if (patternBad(pattern)) {
463 fprintf(stderr, "rinetd: illegal allow or "
464 "deny pattern. Only digits, ., and\n"
465 "the ? and * wild cards are allowed. "
466 "For performance reasons, rinetd\n"
467 "does not look up complete "
468 "host names.\n");
469 continue;
470 }
471
472 allowRules[ai] = malloc(strlen(pattern) + 1);
473 if (!allowRules[ai]) {
474 goto lowMemory;
475 }
476 strcpy(allowRules[ai], pattern);
477 if (i > 0) {
478 if (seAllowRulesTotal[i - 1] == 0) {
479 seAllowRules[i - 1] = ai;
480 }
481 seAllowRulesTotal[i - 1]++;
482 } else {
483 globalAllowRules++;
484 }
485 ai++;
486 } else if (!strcmp(bindAddress, "deny")) {
487 char *pattern = strtok(0, " \t\r\n");
488 if (!pattern) {
489 fprintf(stderr, "rinetd: nothing to deny "
490 "specified on line %d.\n", lnum);
491 continue;
492 }
493 denyRules[di] = malloc(strlen(pattern) + 1);
494 if (!denyRules[di]) {
495 goto lowMemory;
496 }
497 strcpy(denyRules[di], pattern);
498 if (i > 0) {
499 if (seDenyRulesTotal[i - 1] == 0) {
500 seDenyRules[i - 1] = di;
501 }
502 seDenyRulesTotal[i - 1]++;
503 } else {
504 globalDenyRules++;
505 }
506 di++;
507 } else if (!strcmp(bindAddress, "logfile")) {
508 char *nt = strtok(0, " \t\r\n");
509 if (!nt) {
510 fprintf(stderr, "rinetd: no log file name "
511 "specified on line %d.\n", lnum);
512 continue;
513 }
514 logFileName = malloc(strlen(nt) + 1);
515 if (!logFileName) {
516 goto lowMemory;
517 }
518 strcpy(logFileName, nt);
519 } else if (!strcmp(bindAddress, "pidlogfile")) {
520 char *nt = strtok(0, " \t\r\n");
521 if (!nt) {
522 fprintf(stderr, "rinetd: no PID log file name "
523 "specified on line %d.\n", lnum);
524 continue;
525 }
526 pidLogFileName = malloc(strlen(nt) + 1);
527 if (!pidLogFileName) {
528 goto lowMemory;
529 }
530 strcpy(pidLogFileName, nt);
531 } else if (!strcmp(bindAddress, "logcommon")) {
532 logFormatCommon = 1;
533 } else {
534 /* A regular forwarding rule. */
535 bindPortS = strtok(0, " \t\r\n");
536 if (!bindPortS) {
537 fprintf(stderr, "rinetd: no bind port "
538 "specified on line %d.\n", lnum);
539 continue;
540 }
541 service = getservbyname(bindPortS, "tcp");
542 if (service) {
543 bindPort = ntohs(service->s_port);
544 } else {
545 bindPort = atoi(bindPortS);
546 }
547 /* @TCC always false due to data range
548 if ((bindPort == 0) || (bindPort >= 65536)) {
549 fprintf(stderr, "rinetd: bind port missing "
550 "or out of range on line %d.\n", lnum);
551 continue;
552 }
553 */
554 connectAddress = strtok(0, " \t\r\n");
555 if (!connectAddress) {
556 fprintf(stderr, "rinetd: no connect address "
557 "specified on line %d.\n", lnum);
558 continue;
559 }
560 connectPortS = strtok(0, " \t\r\n");
561 if (!connectPortS) {
562 fprintf(stderr, "rinetd: no connect port "
563 "specified on line %d.\n", lnum);
564 continue;
565 }
566 service = getservbyname(connectPortS, "tcp");
567 if (service) {
568 connectPort = ntohs(service->s_port);
569 } else {
570 connectPort = atoi(connectPortS);
571 }
572 /* @TCC always false
573 if ((connectPort == 0) || (connectPort >= 65536)) {
574 fprintf(stderr, "rinetd: bind port missing "
575 "or out of range on line %d.\n", lnum);
576 continue;
577 }
578 */
579 /* Turn all of this stuff into reasonable addresses */
580 if (!getAddress(bindAddress, &iaddr)) {
581 fprintf(stderr, "rinetd: host %s could not be "
582 "resolved on line %d.\n",
583 bindAddress, lnum);
584 continue;
585 }
586 /* Make a server socket */
587 seFds[i] = socket(PF_INET, SOCK_STREAM, 0);
588 if (seFds[i] == INVALID_SOCKET) {
589 fprintf(stderr, "rinetd: couldn't create "
590 "server socket!\n");
591 seFds[i] = -1;
592 continue;
593 }
594 #ifndef WIN32
595 if (seFds[i] > maxfd) {
596 maxfd = seFds[i];
597 }
598 #endif
599 saddr.sin_family = AF_INET;
600 memcpy(&saddr.sin_addr, &iaddr, sizeof(iaddr));
601 saddr.sin_port = htons(bindPort);
602 j = 1;
603 setsockopt(seFds[i], SOL_SOCKET, SO_REUSEADDR,
604 (const char *) &j, sizeof(j));
605 if (bind(seFds[i], (struct sockaddr *)
606 &saddr, sizeof(saddr)) == SOCKET_ERROR)
607 {
608 /* Warn -- don't exit. */
609 fprintf(stderr, "rinetd: couldn't bind to "
610 "address %s port %d\n",
611 bindAddress, bindPort);
612 closesocket(seFds[i]);
613 seFds[i] = INVALID_SOCKET;
614 continue;
615 }
616 if (listen(seFds[i], 5) == SOCKET_ERROR) {
617 /* Warn -- don't exit. */
618 fprintf(stderr, "rinetd: couldn't listen to "
619 "address %s port %d\n",
620 bindAddress, bindPort);
621 closesocket(seFds[i]);
622 seFds[i] = INVALID_SOCKET;
623 continue;
624 }
625 ioctlsocket(seFds[i], FIONBIO, &j);
626 if (!getAddress(connectAddress, &iaddr)) {
627 /* Warn -- don't exit. */
628 fprintf(stderr, "rinetd: host %s could not be "
629 "resolved on line %d.\n",
630 bindAddress, lnum);
631 closesocket(seFds[i]);
632 seFds[i] = INVALID_SOCKET;
633 continue;
634 }
635 seLocalAddrs[i] = iaddr;
636 seLocalPorts[i] = htons(connectPort);
637 seFromHosts[i] = malloc(strlen(bindAddress) + 1);
638 if (!seFromHosts[i]) {
639 goto lowMemory;
640 }
641 strcpy(seFromHosts[i], bindAddress);
642 seFromPorts[i] = bindPort;
643 seToHosts[i] = malloc(strlen(connectAddress) + 1);
644 if (!seToHosts[i]) {
645 goto lowMemory;
646 }
647 strcpy(seToHosts[i], connectAddress);
648 seToPorts[i] = connectPort;
649 i++;
650 if (i < seTotal) {
651 seAllowRulesTotal[i] = 0;
652 seDenyRulesTotal[i] = 0;
653 }
654 }
655 }
656 /* Open the log file */
657 if (logFile) {
658 fclose(logFile);
659 logFile = 0;
660 }
661 if (logFileName) {
662 logFile = fopen(logFileName, "a");
663 if (!logFile) {
664 fprintf(stderr, "rinetd: could not open %s to append.\n",
665 logFileName);
666 }
667 }
668 return;
669 lowMemory:
670 fprintf(stderr, "rinetd: not enough memory to start rinetd.\n");
671 exit(1);
672 }
673
674 int getConfLine(FILE *in, char *line, int space, int *lnum)
675 {
676 char *p;
677 while (1) {
678 if (!fgets(line, space, in)) {
679 return 0;
680 }
681 p = line;
682 while (isspace(*p)) {
683 p++;
684 }
685 if (!(*p)) {
686 /* Blank lines are OK */
687 continue;
688 }
689 if (*p == '#') {
690 /* Comment lines are also OK */
691 continue;
692 }
693 (*lnum)++;
694 return 1;
695 }
696 }
697
698 void initArrays(void)
699 {
700 int j;
701 coTotal = 64;
702 reFds = (SOCKET *) malloc(sizeof(int) * coTotal);
703 loFds = (SOCKET *) malloc(sizeof(int) * coTotal);
704 coInputRPos = (int *) malloc(sizeof(int) * coTotal);
705 coInputWPos = (int *) malloc(sizeof(int) * coTotal);
706 coOutputRPos = (int *) malloc(sizeof(int) * coTotal);
707 coOutputWPos = (int *) malloc(sizeof(int) * coTotal);
708 coClosed = (int *) malloc(sizeof(int) * coTotal);
709 coClosing = (int *) malloc(sizeof(int) * coTotal);
710 reClosed = (int *) malloc(sizeof(int) * coTotal);
711 loClosed = (int *) malloc(sizeof(int) * coTotal);
712 coInput = (char **) malloc(sizeof(char *) * coTotal);
713 coOutput = (char **) malloc(sizeof(char *) * coTotal);
714 coBytesInput = (int *) malloc(sizeof(int) * coTotal);
715 coBytesOutput = (int *) malloc(sizeof(int) * coTotal);
716 reAddresses = (unsigned char *) malloc(coTotal * 4);
717 coLog = (int *) malloc(sizeof(int) * coTotal);
718 coSe = (int *) malloc(sizeof(int) * coTotal);
719 if ((!reFds) || (!loFds) || (!coInputRPos) || (!coInputWPos) ||
720 (!coOutputRPos) || (!coOutputWPos) ||
721 (!coClosed) || (!coClosing) ||
722 (!reClosed) || (!loClosed) ||
723 (!coInput) || (!coOutput) ||
724 (!coBytesInput) || (!coBytesOutput) ||
725 (!coLog) || (!coSe) || (!reAddresses))
726 {
727 fprintf(stderr, "rinetd: not enough memory to start rinetd.\n");
728 exit(1);
729 }
730 for (j = 0; (j < coTotal); j++) {
731 coClosed[j] = 1;
732 coInput[j] = (char *) malloc(sizeof(char) * bufferSpace);
733 coOutput[j] = (char *) malloc(sizeof(char) * bufferSpace);
734 if ((!coInput[j]) || (!coOutput[j])) {
735 fprintf(stderr, "rinetd: not enough memory to start "
736 "rinetd.\n");
737 exit(1);
738 }
739 }
740 }
741
742 void selectPass(void);
743
744 void selectLoop(void) {
745 while (1) {
746 selectPass();
747 }
748 }
749
750 void handleRemoteWrite(int i);
751 void handleRemoteRead(int i);
752 void handleLocalWrite(int i);
753 void handleLocalRead(int i);
754 void handleCloseFromLocal(int i);
755 void handleCloseFromRemote(int i);
756 void handleAccept(int i);
757 void openLocalFd(int se, int i);
758 int getAddress(char *host, struct in_addr *iaddr);
759
760 void selectPass(void) {
761 int i;
762 fd_set readfds, writefds;
763 FD_ZERO(&readfds);
764 FD_ZERO(&writefds);
765 /* Server sockets */
766 for (i = 0; (i < seTotal); i++) {
767 if (seFds[i] != INVALID_SOCKET) {
768 FD_SET(seFds[i], &readfds);
769 }
770 }
771 /* Connection sockets */
772 for (i = 0; (i < coTotal); i++) {
773 if (coClosed[i]) {
774 continue;
775 }
776 if (coClosing[i]) {
777 if (!reClosed[i]) {
778 FD_SET(reFds[i], &writefds);
779 }
780 if (!loClosed[i]) {
781 FD_SET(loFds[i], &writefds);
782 }
783 }
784 /* Get more input if we have room for it */
785 if ((!reClosed[i]) && (coInputRPos[i] < bufferSpace)) {
786 FD_SET(reFds[i], &readfds);
787 }
788 /* Send more output if we have any */
789 if ((!reClosed[i]) && (coOutputWPos[i] < coOutputRPos[i])) {
790 FD_SET(reFds[i], &writefds);
791 }
792 /* Accept more output from the local
793 server if there's room */
794 if ((!loClosed[i]) && (coOutputRPos[i] < bufferSpace)) {
795 FD_SET(loFds[i], &readfds);
796 }
797 /* Send more input to the local server
798 if we have any */
799 if ((!loClosed[i]) && (coInputWPos[i] < coInputRPos[i])) {
800 FD_SET(loFds[i], &writefds);
801 }
802 }
803 select(maxfd + 1, &readfds, &writefds, 0, 0);
804 for (i = 0; (i < seTotal); i++) {
805 if (seFds[i] != -1) {
806 if (FD_ISSET(seFds[i], &readfds)) {
807 handleAccept(i);
808 }
809 }
810 }
811 for (i = 0; (i < coTotal); i++) {
812 if (coClosed[i]) {
813 continue;
814 }
815 if (!reClosed[i]) {
816 if (FD_ISSET(reFds[i], &readfds)) {
817 handleRemoteRead(i);
818 }
819 }
820 if (!reClosed[i]) {
821 if (FD_ISSET(reFds[i], &writefds)) {
822 handleRemoteWrite(i);
823 }
824 }
825 if (!loClosed[i]) {
826 if (FD_ISSET(loFds[i], &readfds)) {
827 handleLocalRead(i);
828 }
829 }
830 if (!loClosed[i]) {
831 if (FD_ISSET(loFds[i], &writefds)) {
832 handleLocalWrite(i);
833 }
834 }
835 if (loClosed[i] && reClosed[i]) {
836 coClosed[i] = 1;
837 }
838 }
839 }
840
841 void handleRemoteRead(int i)
842 {
843 int got;
844 if (bufferSpace == coInputRPos[i]) {
845 return;
846 }
847 got = recv(reFds[i], coInput[i] + coInputRPos[i],
848 bufferSpace - coInputRPos[i], 0);
849 if (got == 0) {
850 /* Prepare for closing */
851 handleCloseFromRemote(i);
852 return;
853 }
854 if (got < 0) {
855 if (GetLastError() == WSAEWOULDBLOCK) {
856 return;
857 }
858 if (GetLastError() == WSAEINPROGRESS) {
859 return;
860 }
861 handleCloseFromRemote(i);
862 return;
863 }
864 coBytesInput[i] += got;
865 coInputRPos[i] += got;
866 }
867
868 void handleRemoteWrite(int i)
869 {
870 int got;
871 if (coClosing[i] && (coOutputWPos[i] == coOutputRPos[i])) {
872 reClosed[i] = 1;
873 coClosed[i] = 1;
874 PERROR("rinetd: local closed and no more output");
875 local_log(i, coSe[i], logDone | coLog[i]);
876 closesocket(reFds[i]);
877 return;
878 }
879 got = send(reFds[i], coOutput[i] + coOutputWPos[i],
880 coOutputRPos[i] - coOutputWPos[i], 0);
881 if (got < 0) {
882 if (GetLastError() == WSAEWOULDBLOCK) {
883 return;
884 }
885 if (GetLastError() == WSAEINPROGRESS) {
886 return;
887 }
888 handleCloseFromRemote(i);
889 return;
890 }
891 coOutputWPos[i] += got;
892 if (coOutputWPos[i] == coOutputRPos[i]) {
893 coOutputWPos[i] = 0;
894 coOutputRPos[i] = 0;
895 }
896 coBytesOutput[i] += got;
897 }
898
899 void handleLocalRead(int i)
900 {
901 int got;
902 if (bufferSpace == coOutputRPos[i]) {
903 return;
904 }
905 got = recv(loFds[i], coOutput[i] + coOutputRPos[i],
906 bufferSpace - coOutputRPos[i], 0);
907 if (got == 0) {
908 handleCloseFromLocal(i);
909 return;
910 }
911 if (got < 0) {
912 if (GetLastError() == WSAEWOULDBLOCK) {
913 return;
914 }
915 if (GetLastError() == WSAEINPROGRESS) {
916 return;
917 }
918 handleCloseFromLocal(i);
919 return;
920 }
921 coOutputRPos[i] += got;
922 }
923
924 void handleLocalWrite(int i)
925 {
926 int got;
927 if (coClosing[i] && (coInputWPos[i] == coInputRPos[i])) {
928 loClosed[i] = 1;
929 coClosed[i] = 1;
930 PERROR("remote closed and no more input");
931 local_log(i, coSe[i], logDone | coLog[i]);
932 closesocket(loFds[i]);
933 return;
934 }
935 got = send(loFds[i], coInput[i] + coInputWPos[i],
936 coInputRPos[i] - coInputWPos[i], 0);
937 if (got < 0) {
938 if (GetLastError() == WSAEWOULDBLOCK) {
939 return;
940 }
941 if (GetLastError() == WSAEINPROGRESS) {
942 return;
943 }
944 handleCloseFromLocal(i);
945 return;
946 }
947 coInputWPos[i] += got;
948 if (coInputWPos[i] == coInputRPos[i]) {
949 coInputWPos[i] = 0;
950 coInputRPos[i] = 0;
951 }
952 }
953
954 void handleCloseFromLocal(int i)
955 {
956 //int arg;
957 coClosing[i] = 1;
958 /* The local end fizzled out, so make sure
959 we're all done with that */
960 PERROR("close from local");
961 closesocket(loFds[i]);
962 loClosed[i] = 1;
963 if (!reClosed[i]) {
964 #ifndef LINUX
965 #ifndef WIN32
966 /* Now set up the remote end for a polite closing */
967
968 /* Request a low-water mark equal to the entire
969 output buffer, so the next write notification
970 tells us for sure that we can close the socket. */
971 arg = 1024;
972 setsockopt(reFds[i], SOL_SOCKET, SO_SNDLOWAT,
973 &arg, sizeof(arg));
974 #endif /* WIN32 */
975 #endif /* LINUX */
976 coLog[i] = logLocalClosedFirst;
977 }
978 }
979
980 void handleCloseFromRemote(int i)
981 {
982 //int arg;
983 coClosing[i] = 1;
984 /* The remote end fizzled out, so make sure
985 we're all done with that */
986 PERROR("close from remote");
987 closesocket(reFds[i]);
988 reClosed[i] = 1;
989 if (!loClosed[i]) {
990 #ifndef LINUX
991 #ifndef WIN32
992 /* Now set up the local end for a polite closing */
993
994 /* Request a low-water mark equal to the entire
995 output buffer, so the next write notification
996 tells us for sure that we can close the socket. */
997 arg = 1024;
998 setsockopt(loFds[i], SOL_SOCKET, SO_SNDLOWAT,
999 &arg, sizeof(arg));
1000 #endif /* WIN32 */
1001 #endif /* LINUX */
1002 loClosed[i] = 0;
1003 coLog[i] = logRemoteClosedFirst;
1004 }
1005 }
1006
1007 void refuse(int index, int logCode);
1008
1009 void handleAccept(int i)
1010 {
1011 struct sockaddr addr;
1012 struct sockaddr_in *sin;
1013 unsigned char address[4];
1014 char addressText[64];
1015 int j;
1016 uint addrlen;
1017 int index = -1;
1018 int o;
1019 SOCKET nfd;
1020 addrlen = sizeof(addr);
1021 nfd = accept(seFds[i], &addr, &addrlen);
1022 if (nfd == INVALID_SOCKET) {
1023 local_log(-1, i, logAcceptFailed);
1024 return;
1025 }
1026 #ifndef WIN32
1027 if (nfd > maxfd) {
1028 maxfd = nfd;
1029 }
1030 #endif /* WIN32 */
1031 j = 1;
1032 ioctlsocket(nfd, FIONBIO, &j);
1033 j = 0;
1034 #ifndef WIN32
1035 setsockopt(nfd, SOL_SOCKET, SO_LINGER, &j, sizeof(j));
1036 #endif
1037 for (j = 0; (j < coTotal); j++) {
1038 if (coClosed[j]) {
1039 index = j;
1040 break;
1041 }
1042 }
1043 if (index == -1) {
1044 o = coTotal;
1045 coTotal *= 2;
1046 if (!SAFE_REALLOC(&reFds, sizeof(int) * o,
1047 sizeof(SOCKET) * coTotal))
1048 {
1049 goto shortage;
1050 }
1051 if (!SAFE_REALLOC(&loFds, sizeof(int) * o,
1052 sizeof(SOCKET) * coTotal))
1053 {
1054 goto shortage;
1055 }
1056 if (!SAFE_REALLOC(&coInputRPos,
1057 sizeof(int) * o, sizeof(int) * coTotal))
1058 {
1059 goto shortage;
1060 }
1061 if (!SAFE_REALLOC(&coInputWPos,
1062 sizeof(int) * o, sizeof(int) * coTotal))
1063 {
1064 goto shortage;
1065 }
1066 if (!SAFE_REALLOC(&coOutputRPos,
1067 sizeof(int) * o, sizeof(int) * coTotal))
1068 {
1069 goto shortage;
1070 }
1071 if (!SAFE_REALLOC(&coOutputWPos, sizeof(int) * o,
1072 sizeof(int) * coTotal))
1073 {
1074 goto shortage;
1075 }
1076 if (!SAFE_REALLOC(&coClosed, sizeof(int) * o,
1077 sizeof(int) * coTotal))
1078 {
1079 goto shortage;
1080 }
1081 if (!SAFE_REALLOC(&coClosing, sizeof(int) * o,
1082 sizeof(int) * coTotal))
1083 {
1084 goto shortage;
1085 }
1086 if (!SAFE_REALLOC(&reClosed, sizeof(int) * o,
1087 sizeof(int) * coTotal))
1088 {
1089 goto shortage;
1090 }
1091 if (!SAFE_REALLOC(&loClosed, sizeof(int) * o,
1092 sizeof(int) * coTotal))
1093 {
1094 goto shortage;
1095 }
1096 if (!SAFE_REALLOC(&coLog, sizeof(int) * o,
1097 sizeof(int) * coTotal))
1098 {
1099 goto shortage;
1100 }
1101 if (!SAFE_REALLOC(&coSe, sizeof(int) * o,
1102 sizeof(int) * coTotal))
1103 {
1104 goto shortage;
1105 }
1106 if (!SAFE_REALLOC(&coBytesInput, sizeof(int) * o,
1107 sizeof(int) * coTotal))
1108 {
1109 goto shortage;
1110 }
1111 if (!SAFE_REALLOC(&reAddresses, 4 * o,
1112 4 * coTotal))
1113 {
1114 goto shortage;
1115 }
1116 if (!SAFE_REALLOC(&coBytesOutput, sizeof(int) * o,
1117 sizeof(int) * coTotal))
1118 {
1119 goto shortage;
1120 }
1121 if (!SAFE_REALLOC(&coInput, sizeof(char *) * o,
1122 sizeof(char *) * coTotal))
1123 {
1124 goto shortage;
1125 }
1126 if (!SAFE_REALLOC(&coOutput, sizeof(char *) * o,
1127 sizeof(char *) * coTotal))
1128 {
1129 goto shortage;
1130 }
1131 for (j = o; (j < coTotal); j++) {
1132 coClosed[j] = 1;
1133 coInput[j] = (char *)
1134 malloc(sizeof(char) * bufferSpace);
1135 if (!coInput[j]) {
1136 int k;
1137 for (k = o; (k < j); k++) {
1138 free(coInput[k]);
1139 free(coOutput[k]);
1140 }
1141 goto shortage;
1142 }
1143 coOutput[j] = (char *)
1144 malloc(sizeof(char) * bufferSpace);
1145 if (!coOutput[j]) {
1146 int k;
1147 free(coInput[j]);
1148 for (k = o; (k < j); k++) {
1149 free(coInput[k]);
1150 free(coOutput[k]);
1151 }
1152 goto shortage;
1153 }
1154 }
1155 index = o;
1156 }
1157 coInputRPos[index] = 0;
1158 coInputWPos[index] = 0;
1159 coOutputRPos[index] = 0;
1160 coOutputWPos[index] = 0;
1161 coClosed[index] = 0;
1162 coClosing[index] = 0;
1163 reClosed[index] = 0;
1164 loClosed[index] = 0;
1165 reFds[index] = nfd;
1166 coBytesInput[index] = 0;
1167 coBytesOutput[index] = 0;
1168 coLog[index] = 0;
1169 coSe[index] = i;
1170 sin = (struct sockaddr_in *) &addr;
1171 memcpy(address, &(sin->sin_addr.s_addr), 4);
1172 memcpy(reAddresses + index * 4, address, 4);
1173 /* Now, do we want to accept this connection?
1174 Format it for comparison to a pattern. */
1175 sprintf(addressText, "%d.%d.%d.%d",
1176 address[0], address[1], address[2], address[3]);
1177 /* 1. Check global allow rules. If there are no
1178 global allow rules, it's presumed OK at
1179 this step. If there are any, and it doesn't
1180 match at least one, kick it out. */
1181 if (globalAllowRules) {
1182 int good = 0;
1183 for (j = 0; (j < globalAllowRules); j++) {
1184 if (match(addressText, allowRules[j])) {
1185 good = 1;
1186 break;
1187 }
1188 }
1189 if (!good) {
1190 refuse(index, logNotAllowed);
1191 return;
1192 }
1193 }
1194 /* 2. Check global deny rules. If it matches
1195 any of the global deny rules, kick it out. */
1196 if (globalDenyRules) {
1197 for (j = 0; (j < globalDenyRules); j++) {
1198 if (match(addressText, denyRules[j])) {
1199 refuse(index, logDenied);
1200 }
1201 }
1202 }
1203 /* 3. Check allow rules specific to this forwarding rule.
1204 If there are none, it's OK. If there are any,
1205 it must match at least one. */
1206 if (seAllowRulesTotal[i]) {
1207 int good = 0;
1208 for (j = 0; (j < seAllowRulesTotal[i]); j++) {
1209 if (match(addressText,
1210 allowRules[seAllowRules[i] + j])) {
1211 good = 1;
1212 break;
1213 }
1214 }
1215 if (!good) {
1216 refuse(index, logNotAllowed);
1217 return;
1218 }
1219 }
1220 /* 2. Check deny rules specific to this forwarding rule. If
1221 it matches any of the deny rules, kick it out. */
1222 if (seDenyRulesTotal[i]) {
1223 for (j = 0; (j < seDenyRulesTotal[i]); j++) {
1224 if (match(addressText,
1225 denyRules[seDenyRules[i] + j])) {
1226 refuse(index, logDenied);
1227 }
1228 }
1229 }
1230 /* Now open a connection to the local server.
1231 This, too, is nonblocking. Why wait
1232 for anything when you don't have to? */
1233 openLocalFd(i, index);
1234 return;
1235 shortage:
1236 fprintf(stderr, "rinetd: not enough memory to "
1237 "add slots. Currently %d slots.\n", o);
1238 /* Go back to the previous total number of slots */
1239 coTotal = o;
1240 }
1241
1242 void openLocalFd(int se, int i)
1243 {
1244 int j;
1245 struct sockaddr_in saddr;
1246 loFds[i] = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
1247 if (loFds[i] == INVALID_SOCKET) {
1248 closesocket(reFds[i]);
1249 reClosed[i] = 1;
1250 loClosed[i] = 1;
1251 coClosed[i] = 1;
1252 local_log(i, coSe[i], logLocalSocketFailed);
1253 return;
1254 }
1255 #ifndef WIN32
1256 if (loFds[i] > maxfd) {
1257 maxfd = loFds[i];
1258 }
1259 #endif /* WIN32 */
1260 /* Bind the local socket */
1261 saddr.sin_family = AF_INET;
1262 saddr.sin_port = INADDR_ANY;
1263 saddr.sin_addr.s_addr = 0;
1264 if (bind(loFds[i], (struct sockaddr *) &saddr, sizeof(saddr)) == SOCKET_ERROR) {
1265 closesocket(loFds[i]);
1266 closesocket(reFds[i]);
1267 reClosed[i] = 1;
1268 loClosed[i] = 1;
1269 coClosed[i] = 1;
1270 local_log(i, coSe[i], logLocalBindFailed);
1271 return;
1272 }
1273 memset(&saddr, 0, sizeof(struct sockaddr_in));
1274 saddr.sin_family = AF_INET;
1275 memcpy(&saddr.sin_addr, &seLocalAddrs[se], sizeof(struct in_addr));
1276 saddr.sin_port = seLocalPorts[se];
1277 #ifndef WIN32
1278 #ifdef LINUX
1279 j = 0;
1280 setsockopt(loFds[i], SOL_SOCKET, SO_LINGER, &j, sizeof(j));
1281 #else
1282 j = 1024;
1283 setsockopt(loFds[i], SOL_SOCKET, SO_SNDBUF, &j, sizeof(j));
1284 #endif /* LINUX */
1285 #endif /* WIN32 */
1286 j = 1;
1287 ioctlsocket(loFds[i], FIONBIO, &j);
1288 if (connect(loFds[i], (struct sockaddr *)&saddr,
1289 sizeof(struct sockaddr_in)) == INVALID_SOCKET)
1290 {
1291 if ((GetLastError() != WSAEINPROGRESS) &&
1292 (GetLastError() != WSAEWOULDBLOCK))
1293 {
1294 PERROR("rinetd: connect");
1295 closesocket(loFds[i]);
1296 closesocket(reFds[i]);
1297 reClosed[i] = 1;
1298 loClosed[i] = 1;
1299 coClosed[i] = 1;
1300 local_log(i, coSe[i], logLocalConnectFailed);
1301 return;
1302 }
1303 }
1304 }
1305
1306 int getAddress(char *host, struct in_addr *iaddr)
1307 {
1308 char *p = host;
1309 int ishost = 0;
1310 while (*p) {
1311 if (!(isdigit(*p) || ((*p) == '.'))) {
1312 ishost = 1;
1313 break;
1314 }
1315 p++;
1316 }
1317 if (ishost) {
1318 struct hostent *h;
1319 h = gethostbyname(host);
1320 if (!h) {
1321 return 0;
1322 }
1323 memcpy(
1324 (void *) &iaddr->s_addr,
1325 (void *) h->h_addr,
1326 4);
1327 return 1;
1328 } else {
1329 iaddr->s_addr = inet_addr(host);
1330 return 1;
1331 }
1332 }
1333
1334 #ifndef WIN32
1335 void plumber(int s)
1336 {
1337 /* Just reinstall */
1338 signal(SIGPIPE, plumber);
1339 }
1340
1341 void hup(int s)
1342 {
1343 /* Learn the new rules */
1344 readConfiguration();
1345 /* And reinstall the signal handler */
1346 signal(SIGHUP, hup);
1347 }
1348 #endif /* WIN32 */
1349
1350 int safeRealloc(void **data, int oldsize, int newsize)
1351 {
1352 void *newData = malloc(newsize + 1);
1353 if (!newData) {
1354 return 0;
1355 }
1356 if (newsize < oldsize) {
1357 memcpy(newData, *data, newsize);
1358 } else {
1359 memcpy(newData, *data, oldsize);
1360 }
1361 *data = newData;
1362 return 1;
1363 }
1364
1365 void RegisterPID(void)
1366 {
1367 FILE *pid_file;
1368 char *pid_file_name = "/var/run/rinetd.pid";
1369 if (pidLogFileName) {
1370 pid_file_name = pidLogFileName;
1371 }
1372 /* add other systems with wherever they register processes */
1373 #if defined(LINUX)
1374 pid_file = fopen(pid_file_name, "w");
1375 if (pid_file == NULL) {
1376 /* non-fatal, non-Linux may lack /var/run... */
1377 fprintf(stderr, "rinetd: Couldn't write to "
1378 "%s. PID was not logged.\n", pid_file_name);
1379 } else {
1380 /* error checking deliberately omitted */
1381 fprintf(pid_file, "%d\n", getpid());
1382 fclose(pid_file);
1383 }
1384 #endif /* LINUX */
1385 }
1386
1387 unsigned char nullAddress[4] = { 0, 0, 0, 0 };
1388
1389 struct tm *get_gmtoff(int *tz);
1390
1391 void local_log(int i, int coSe, int result)
1392 {
1393 unsigned char *reAddress;
1394 int bytesOutput;
1395 int bytesInput;
1396 /* Bit of borrowing from Apache logging module here,
1397 thanks folks */
1398 int timz;
1399 struct tm *t;
1400 char tstr[1024];
1401 char sign;
1402 /* @TCC I have no fing clue what this does (but always true, so don't)
1403 if (!local_log) {
1404 return;
1405 }
1406 */
1407 t = get_gmtoff(&timz);
1408 sign = (timz < 0 ? '-' : '+');
1409 if (timz < 0) {
1410 timz = -timz;
1411 }
1412 strftime(tstr, sizeof(tstr), "%d/%b/%Y:%H:%M:%S ", t);
1413
1414 if (i != -1) {
1415 reAddress = reAddresses + i * 4;
1416 bytesOutput = coBytesOutput[i];
1417 bytesInput = coBytesInput[i];
1418 } else {
1419 reAddress = nullAddress;
1420 bytesOutput = 0;
1421 bytesInput = 0;
1422 }
1423 if (logFile) {
1424 if (logFormatCommon) {
1425 /* Fake a common log format log file in a way that
1426 most web analyzers can do something interesting with.
1427 We lie and say the protocol is HTTP because we don't
1428 want the web analyzer to reject the line. We also
1429 lie and claim success (code 200) because we don't
1430 want the web analyzer to ignore the line as an
1431 error and not analyze the "URL." We put a result
1432 message into our "URL" instead. The last field
1433 is an extra, giving the number of input bytes,
1434 after several placeholders meant to fill the
1435 positions frequently occupied by user agent,
1436 referrer, and server name information. */
1437 fprintf(logFile, "%d.%d.%d.%d - - "
1438 "[%s %c%.2d%.2d] "
1439 "\"GET /rinetd-services/%s/%d/%s/%d/%s HTTP/1.0\" "
1440 "200 %d - - - %d\n",
1441 reAddress[0],
1442 reAddress[1],
1443 reAddress[2],
1444 reAddress[3],
1445 tstr,
1446 sign,
1447 timz / 60,
1448 timz % 60,
1449 seFromHosts[coSe], seFromPorts[coSe],
1450 seToHosts[coSe], seToPorts[coSe],
1451 logMessages[result],
1452 bytesOutput,
1453 bytesInput);
1454 } else {
1455 /* Write an rinetd-specific log entry with a
1456 less goofy format. */
1457 fprintf(logFile, "%s\t%d.%d.%d.%d\t%s\t%d\t%s\t%d\t%d"
1458 "\t%d\t%s\n",
1459 tstr,
1460 reAddress[0],
1461 reAddress[1],
1462 reAddress[2],
1463 reAddress[3],
1464 seFromHosts[coSe], seFromPorts[coSe],
1465 seToHosts[coSe], seToPorts[coSe],
1466 bytesInput,
1467 bytesOutput,
1468 logMessages[result]);
1469 }
1470 }
1471 }
1472
1473 int readArgs (int argc,
1474 char **argv,
1475 RinetdOptions *options)
1476 {
1477 int c;
1478
1479 while (1) {
1480 int option_index = 0;
1481 static struct option long_options[] = {
1482 {"conf-file", 1, 0, 'c'},
1483 {"help", 0, 0, 'h'},
1484 {"version", 0, 0, 'v'},
1485 {0, 0, 0, 0}
1486 };
1487 c = getopt_long (argc, argv, "c:shv",
1488 long_options, &option_index);
1489 if (c == -1) {
1490 break;
1491 }
1492 switch (c) {
1493 case 'c':
1494 options->conf_file = malloc(strlen(optarg) + 1);
1495 if (!options->conf_file) {
1496 fprintf(stderr, "Not enough memory to "
1497 "launch rinetd.\n");
1498 exit(1);
1499 }
1500 strcpy(options->conf_file, optarg);
1501 break;
1502 case 'h':
1503 printf("Usage: rinetd [OPTION]\n"
1504 " -c, --conf-file FILE read configuration "
1505 "from FILE\n"
1506 " -h, --help display this help\n"
1507 " -v, --version display version "
1508 "number\n\n");
1509 printf("Most options are controlled through the\n"
1510 "configuration file. See the rinetd(8)\n"
1511 "manpage for more information.\n");
1512 exit (0);
1513 case 'v':
1514 printf ("rinetd %s\n", VERSION);
1515 exit (0);
1516 case '?':
1517 default:
1518 exit (1);
1519 }
1520 }
1521 return 0;
1522 }
1523
1524 /* get_gmtoff was borrowed from Apache. Thanks folks. */
1525
1526 struct tm *get_gmtoff(int *tz) {
1527 time_t tt = time(NULL);
1528 struct tm gmt;
1529 struct tm *t;
1530 int days, hours, minutes;
1531
1532 /* Assume we are never more than 24 hours away. */
1533 gmt = *gmtime(&tt); /* remember gmtime/localtime return ptr to static */
1534 t = localtime(&tt); /* buffer... so be careful */
1535 days = t->tm_yday - gmt.tm_yday;
1536 hours = ((days < -1 ? 24 : 1 < days ? -24 : days * 24)
1537 + t->tm_hour - gmt.tm_hour);
1538 minutes = hours * 60 + t->tm_min - gmt.tm_min;
1539 *tz = minutes;
1540 return t;
1541 }
1542
1543 int patternBad(char *pattern)
1544 {
1545 char *p = pattern;
1546 while (*p) {
1547 if (isdigit(*p) || ((*p) == '?') || ((*p) == '*') ||
1548 ((*p) == '.'))
1549 {
1550 p++;
1551 }
1552 return 0;
1553 }
1554 return 1;
1555 }
1556
1557 void refuse(int index, int logCode)
1558 {
1559 closesocket(reFds[index]);
1560 reClosed[index] = 1;
1561 loClosed[index] = 1;
1562 coClosed[index] = 1;
1563 local_log(index, coSe[index], logCode);
1564 }
1565
1566 void term(int s)
1567 {
1568 /* Obey the request, but first flush the log */
1569 if (logFile) {
1570 fclose(logFile);
1571 }
1572 exit(0);
1573 }
1574
1575
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.