📄 rinetd.c
字号:
#define VERSION "0.62"
#ifdef WIN32
#include <windows.h>
#include <winsock.h>
#include "getopt.h"
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>#include <netdb.h>
#include <netinet/in.h>
#include <getopt.h>
#include <errno.h>
#define INVALID_SOCKET (-1)
#include <sys/time.h>
#endif /* WIN32 */
#include <stdio.h>#include <string.h>#include <signal.h>#include <stdlib.h>#include <fcntl.h>#include <time.h>#include <ctype.h>
#ifndef WIN32
/* Windows sockets compatibility defines */
#define INVALID_SOCKET (-1)
#define SOCKET_ERROR (-1)
int closesocket(int s);
int closesocket(int s) {
return close(s);
}
#define ioctlsocket ioctl
#define MAKEWORD(a, b)
#define WSAStartup(a, b) (0)
#define WSACleanup()
#ifdef __MAC__
/* The constants for these are a little screwy in the prelinked
MSL GUSI lib and we can't rebuild it, so roll with it */
#define WSAEWOULDBLOCK EWOULDBLOCK
#define WSAEAGAIN EAGAIN
#define WSAEINPROGRESS EINPROGRESS
#else
#define WSAEWOULDBLOCK EWOULDBLOCK
#define WSAEAGAIN EAGAIN
#define WSAEINPROGRESS EINPROGRESS
#endif /* __MAC__ */
#define WSAEINTR EINTR
#define SOCKET int
#define GetLastError() (errno)
typedef struct {
int dummy;
} WSADATA;
void Sleep(long ms);
void Sleep(long ms)
{
struct timeval tv;
tv.tv_sec = ms / 1000;
tv.tv_usec = ms * 1000;
select(0, 0, 0, 0, &tv);
}
#else
/* WIN32 doesn't really have WSAEAGAIN */
#ifndef WSAEAGAIN
#define WSAEAGAIN WSAEWOULDBLOCK
#endif
#endif /* WIN32 */
#ifndef TRUE#define TRUE 1#endif#ifndef FALSE#define FALSE 0#endif#ifdef DEBUG#define PERROR perror#else#define PERROR(x) #endif /* DEBUG *//* We've got to get FIONBIO from somewhere. Try the Solaris location if it isn't defined yet by the above includes. */#ifndef FIONBIO#include <sys/filio.h>#endif /* FIONBIO */#include "match.h"
SOCKET *seFds = 0;/* In network order, for network purposes */struct in_addr *seLocalAddrs = 0;unsigned short *seLocalPorts = 0;/* In ASCII and local byte order, for logging purposes */char **seFromHosts;int *seFromPorts;char **seToHosts;int *seToPorts;/* Offsets into list of allow and deny rules. Any rules prior to globalAllowRules and globalDenyRules are global rules. */int *seAllowRules = 0;int *seAllowRulesTotal = 0;int globalAllowRules = 0;int *seDenyRules = 0;int *seDenyRulesTotal = 0;int globalDenyRules = 0;SOCKET *reFds = 0;SOCKET *loFds = 0;unsigned char *reAddresses = 0;int *coInputRPos = 0;int *coInputWPos = 0;int *coOutputRPos = 0;int *coOutputWPos = 0;int *coClosed = 0;int *coClosing = 0;int *reClosed = 0;int *loClosed = 0;int *coBytesInput = 0;int *coBytesOutput = 0;int *coLog = 0;int *coSe = 0;char **coInput = 0;char **coOutput = 0;char **allowRules = 0;char **denyRules = 0;int *denyRulesFor = 0;int seTotal = 0;int coTotal = 0;int allowRulesTotal = 0;int denyRulesTotal = 0;int maxfd = 0;char *logFileName = 0;char *pidLogFileName = 0;int logFormatCommon = 0;FILE *logFile = 0;/* If 'newsize' bytes can be allocated, *data is set to point to them, the previous data is copied, and 1 is returned. If 'size' bytes cannot be allocated, *data is UNCHANGED, and 0 is returned. */ #define SAFE_REALLOC(x, y, z) safeRealloc((void **) (x), (y), (z))int safeRealloc(void **data, int oldsize, int newsize);/* se: (se)rver sockets re: (re)mote sockets lo: (lo)cal sockets (being redirected to) co: connections*/#define bufferSpace 1024void readConfiguration();/* Signal handlers */void plumber(int s);void hup(int s);void term(int s);void initArrays(void);void RegisterPID(void);void selectLoop(void);void log(int i, int coSe, int result);
int getAddress(char *host, struct in_addr *iaddr);
char *logMessages[] = { "done-local-closed", "done-remote-closed", "accept-failed -", 0, "local-socket-failed -", 0, "local-bind-failed -", 0, "local-connect-failed -", 0, "not-allowed", 0, "denied", 0}; #define logDone 0#define logAcceptFailed 2#define logLocalSocketFailed 4#define logLocalBindFailed 6#define logLocalConnectFailed 8#define logNotAllowed 10#define logDenied 12#define logLocalClosedFirst 0#define logRemoteClosedFirst 1/* Option parsing */typedef struct _rinetd_options RinetdOptions;struct _rinetd_options{ char *conf_file;};RinetdOptions options = { "/etc/rinetd.conf"};int readArgs (int argc, char **argv, RinetdOptions *options);int main(int argc, char *argv[]){
WSADATA wsaData;
int result = WSAStartup(MAKEWORD(1, 1), &wsaData);
if (result != 0) {
fprintf(stderr, "Your computer was not connected "
"to the Internet at the time that "
"this program was launched, or you "
"do not have a 32-bit "
"connection to the Internet.");
exit(1);
}
readArgs(argc, argv, &options);#ifndef WIN32
#ifndef DEBUG if (!fork()) { if (!fork()) {#endif /* DEBUG */ signal(SIGPIPE, plumber); signal(SIGHUP, hup);#endif /* WIN32 */
signal(SIGTERM, term); initArrays(); readConfiguration(); RegisterPID(); selectLoop();#ifndef WIN32
#ifndef DEBUG } else { exit(0); } } else { exit(0); }#endif /* DEBUG */#endif /* WIN32 */
return 0;}int getConfLine(FILE *in, char *line, int space, int *lnum);int patternBad(char *pattern);void readConfiguration(void){ FILE *in; char line[16384]; int lnum = 0; int i; int ai; int di; if (seFds) { /* Close existing server sockets. */ for (i = 0; (i < seTotal); i++) { if (seFds[i] != -1) { closesocket(seFds[i]); free(seFromHosts[i]); free(seToHosts[i]); } } /* Free memory associated with previous set. */ free(seFds); free(seLocalAddrs); free(seLocalPorts); free(seFromHosts); free(seFromPorts); free(seToHosts); free(seToPorts); free(seAllowRules); free(seDenyRules); free(seAllowRulesTotal); free(seDenyRulesTotal); } seTotal = 0; if (allowRules) { /* Forget existing allow rules. */ for (i = 0; (i < allowRulesTotal); i++) { free(allowRules[i]); } /* Free memory associated with previous set. */ free(allowRules); globalAllowRules = 0; } allowRulesTotal = 0; if (denyRules) { /* Forget existing deny rules. */ for (i = 0; (i < denyRulesTotal); i++) { free(denyRules[i]); } /* Free memory associated with previous set. */ free(denyRules); globalDenyRules = 0; } denyRulesTotal = 0; if (logFileName) { free(logFileName); logFileName = 0; } if (pidLogFileName) { free(pidLogFileName); pidLogFileName = 0; } /* 1. Count the non-comment lines of each type and allocate space for the data. */ in = fopen(options.conf_file, "r"); if (!in) { fprintf(stderr, "rinetd: can't open %s\n", options.conf_file); exit(1); } while (1) { char *t = 0; if (!getConfLine(in, line, sizeof(line), &lnum)) { break; } t = strtok(line, " \t\r\n"); if (!strcmp(t, "logfile")) { continue; } else if (!strcmp(t, "pidlogfile")) { continue; } else if (!strcmp(t, "logcommon")) { continue; } else if (!strcmp(t, "allow")) { allowRulesTotal++; } else if (!strcmp(t, "deny")) { denyRulesTotal++; } else { /* A regular forwarding rule */ seTotal++; } } fclose(in); seFds = (SOCKET *) malloc(sizeof(int) * seTotal); if (!seFds) { goto lowMemory; } seLocalAddrs = (struct in_addr *) malloc(sizeof(struct in_addr) * seTotal); if (!seLocalAddrs) { goto lowMemory; } seLocalPorts = (unsigned short *) malloc(sizeof(unsigned short) * seTotal); if (!seLocalPorts) { goto lowMemory; } seFromHosts = (char **) malloc(sizeof(char *) * seTotal); if (!seFromHosts) { goto lowMemory; } seFromPorts = (int *) malloc(sizeof(int) * seTotal); if (!seFromPorts) { goto lowMemory; } seToHosts = (char **) malloc(sizeof(char *) * seTotal); if (!seToHosts) { goto lowMemory; } seToPorts = (int *) malloc(sizeof(int) * seTotal); if (!seToPorts) { goto lowMemory; } allowRules = (char **) malloc(sizeof(char *) * allowRulesTotal); if (!allowRules) { goto lowMemory; } denyRules = (char **) malloc(sizeof(char *) * denyRulesTotal); if (!denyRules) { goto lowMemory; } seAllowRules = (int *) malloc(sizeof(int) * seTotal); if (!seAllowRules) { goto lowMemory; } seAllowRulesTotal = (int *) malloc(sizeof(int) * seTotal); if (!seAllowRulesTotal) { goto lowMemory; } seDenyRules = (int *) malloc(sizeof(int) * seTotal); if (!seDenyRules) { goto lowMemory; } seDenyRulesTotal = (int *) malloc(sizeof(int) * seTotal); if (!seDenyRulesTotal) { goto lowMemory; } /* 2. Make a second pass to configure them. */ i = 0; ai = 0; di = 0; lnum = 0; in = fopen(options.conf_file, "r"); if (!in) { goto lowMemory; } if (seTotal > 0) { seAllowRulesTotal[i] = 0; seDenyRulesTotal[i] = 0; } while (1) { char *bindAddress; unsigned short bindPort; char *connectAddress; char *bindPortS; char *connectPortS; unsigned short connectPort; struct in_addr iaddr; struct sockaddr_in saddr; struct servent *service; int j; if (!getConfLine(in, line, sizeof(line), &lnum)) { break; } bindAddress = strtok(line, " \t\r\n"); if (!bindAddress) { fprintf(stderr, "rinetd: no bind address specified " "on line %d.\n", lnum); continue; } if (!strcmp(bindAddress, "allow")) { char *pattern = strtok(0, " \t\r\n"); if (!pattern) { fprintf(stderr, "rinetd: nothing to allow " "specified on line %d.\n", lnum); continue; } if (patternBad(pattern)) { fprintf(stderr, "rinetd: illegal allow or " "deny pattern. Only digits, ., and\n" "the ? and * wild cards are allowed. " "For performance reasons, rinetd\n" "does not look up complete " "host names.\n"); continue; } allowRules[ai] = malloc(strlen(pattern) + 1); if (!allowRules[ai]) { goto lowMemory; } strcpy(allowRules[ai], pattern); if (i > 0) { if (seAllowRulesTotal[i - 1] == 0) { seAllowRules[i - 1] = ai; } seAllowRulesTotal[i - 1]++; } else { globalAllowRules++; } ai++; } else if (!strcmp(bindAddress, "deny")) { char *pattern = strtok(0, " \t\r\n"); if (!pattern) { fprintf(stderr, "rinetd: nothing to deny " "specified on line %d.\n", lnum); continue; } denyRules[di] = malloc(strlen(pattern) + 1); if (!denyRules[di]) { goto lowMemory; } strcpy(denyRules[di], pattern); if (i > 0) { if (seDenyRulesTotal[i - 1] == 0) { seDenyRules[i - 1] = di; } seDenyRulesTotal[i - 1]++; } else { globalDenyRules++; } di++; } else if (!strcmp(bindAddress, "logfile")) { char *nt = strtok(0, " \t\r\n"); if (!nt) { fprintf(stderr, "rinetd: no log file name " "specified on line %d.\n", lnum); continue; } logFileName = malloc(strlen(nt) + 1); if (!logFileName) { goto lowMemory; } strcpy(logFileName, nt); } else if (!strcmp(bindAddress, "pidlogfile")) { char *nt = strtok(0, " \t\r\n"); if (!nt) { fprintf(stderr, "rinetd: no PID log file name " "specified on line %d.\n", lnum); continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -