~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
cvs/emstar/devel/remote_storage/rinetd/rinetd.c


  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.