📄 rinetd.c
字号:
pidLogFileName = malloc(strlen(nt) + 1); if (!pidLogFileName) { goto lowMemory; } strcpy(pidLogFileName, nt); } else if (!strcmp(bindAddress, "logcommon")) { logFormatCommon = 1; } else { /* A regular forwarding rule. */ bindPortS = strtok(0, " \t\r\n"); if (!bindPortS) { fprintf(stderr, "rinetd: no bind port " "specified on line %d.\n", lnum); continue; } service = getservbyname(bindPortS, "tcp"); if (service) { bindPort = ntohs(service->s_port); } else { bindPort = atoi(bindPortS); } if ((bindPort == 0) || (bindPort >= 65536)) { fprintf(stderr, "rinetd: bind port missing " "or out of range on line %d.\n", lnum); continue; } connectAddress = strtok(0, " \t\r\n"); if (!connectAddress) { fprintf(stderr, "rinetd: no connect address " "specified on line %d.\n", lnum); continue; } connectPortS = strtok(0, " \t\r\n"); if (!connectPortS) { fprintf(stderr, "rinetd: no connect port " "specified on line %d.\n", lnum); continue; } service = getservbyname(connectPortS, "tcp"); if (service) { connectPort = ntohs(service->s_port); } else { connectPort = atoi(connectPortS); } if ((connectPort == 0) || (connectPort >= 65536)) { fprintf(stderr, "rinetd: bind port missing " "or out of range on line %d.\n", lnum); continue; } /* Turn all of this stuff into reasonable addresses */ if (!getAddress(bindAddress, &iaddr)) { fprintf(stderr, "rinetd: host %s could not be " "resolved on line %d.\n", bindAddress, lnum); continue; } /* Make a server socket */ seFds[i] = socket(PF_INET, SOCK_STREAM, 0); if (seFds[i] == INVALID_SOCKET) { fprintf(stderr, "rinetd: couldn't create " "server socket!\n"); seFds[i] = -1; continue; }
#ifndef WIN32 if (seFds[i] > maxfd) { maxfd = seFds[i]; }#endif
saddr.sin_family = AF_INET; memcpy(&saddr.sin_addr, &iaddr, sizeof(iaddr)); saddr.sin_port = htons(bindPort); j = 1; setsockopt(seFds[i], SOL_SOCKET, SO_REUSEADDR, (const char *) &j, sizeof(j)); if (bind(seFds[i], (struct sockaddr *) &saddr, sizeof(saddr)) == SOCKET_ERROR) { /* Warn -- don't exit. */ fprintf(stderr, "rinetd: couldn't bind to " "address %s port %d\n", bindAddress, bindPort); closesocket(seFds[i]); seFds[i] = INVALID_SOCKET; continue; } if (listen(seFds[i], 5) == SOCKET_ERROR) { /* Warn -- don't exit. */ fprintf(stderr, "rinetd: couldn't listen to " "address %s port %d\n", bindAddress, bindPort); closesocket(seFds[i]); seFds[i] = INVALID_SOCKET; continue; }
ioctlsocket(seFds[i], FIONBIO, &j);
if (!getAddress(connectAddress, &iaddr)) { /* Warn -- don't exit. */ fprintf(stderr, "rinetd: host %s could not be " "resolved on line %d.\n", bindAddress, lnum); closesocket(seFds[i]); seFds[i] = INVALID_SOCKET; continue; } seLocalAddrs[i] = iaddr; seLocalPorts[i] = htons(connectPort); seFromHosts[i] = malloc(strlen(bindAddress) + 1); if (!seFromHosts[i]) { goto lowMemory; } strcpy(seFromHosts[i], bindAddress); seFromPorts[i] = bindPort; seToHosts[i] = malloc(strlen(connectAddress) + 1); if (!seToHosts[i]) { goto lowMemory; } strcpy(seToHosts[i], connectAddress); seToPorts[i] = connectPort; i++; if (i < seTotal) { seAllowRulesTotal[i] = 0; seDenyRulesTotal[i] = 0; } } } /* Open the log file */ if (logFile) { fclose(logFile); logFile = 0; } if (logFileName) { logFile = fopen(logFileName, "a"); if (!logFile) { fprintf(stderr, "rinetd: could not open %s to append.\n", logFileName); } } return;lowMemory: fprintf(stderr, "rinetd: not enough memory to start rinetd.\n"); exit(1);}int getConfLine(FILE *in, char *line, int space, int *lnum){ char *p; while (1) { if (!fgets(line, space, in)) { return 0; } p = line; while (isspace(*p)) { p++; } if (!(*p)) { /* Blank lines are OK */ continue; } if (*p == '#') { /* Comment lines are also OK */ continue; } (*lnum)++; return 1; }}void initArrays(void){ int j; coTotal = 64; reFds = (SOCKET *) malloc(sizeof(int) * coTotal); loFds = (SOCKET *) malloc(sizeof(int) * coTotal); coInputRPos = (int *) malloc(sizeof(int) * coTotal); coInputWPos = (int *) malloc(sizeof(int) * coTotal); coOutputRPos = (int *) malloc(sizeof(int) * coTotal); coOutputWPos = (int *) malloc(sizeof(int) * coTotal); coClosed = (int *) malloc(sizeof(int) * coTotal); coClosing = (int *) malloc(sizeof(int) * coTotal); reClosed = (int *) malloc(sizeof(int) * coTotal); loClosed = (int *) malloc(sizeof(int) * coTotal); coInput = (char **) malloc(sizeof(char *) * coTotal); coOutput = (char **) malloc(sizeof(char *) * coTotal); coBytesInput = (int *) malloc(sizeof(int) * coTotal); coBytesOutput = (int *) malloc(sizeof(int) * coTotal); reAddresses = (unsigned char *) malloc(coTotal * 4); coLog = (int *) malloc(sizeof(int) * coTotal); coSe = (int *) malloc(sizeof(int) * coTotal); if ((!reFds) || (!loFds) || (!coInputRPos) || (!coInputWPos) || (!coOutputRPos) || (!coOutputWPos) || (!coClosed) || (!coClosing) || (!reClosed) || (!loClosed) || (!coInput) || (!coOutput) || (!coBytesInput) || (!coBytesOutput) || (!coLog) || (!coSe) || (!reAddresses)) { fprintf(stderr, "rinetd: not enough memory to start rinetd.\n"); exit(1); } for (j = 0; (j < coTotal); j++) { coClosed[j] = 1; coInput[j] = (char *) malloc(sizeof(char) * bufferSpace); coOutput[j] = (char *) malloc(sizeof(char) * bufferSpace); if ((!coInput[j]) || (!coOutput[j])) { fprintf(stderr, "rinetd: not enough memory to start " "rinetd.\n"); exit(1); } }}void selectPass(void);void selectLoop(void) { while (1) { selectPass(); }}void handleRemoteWrite(int i);void handleRemoteRead(int i);void handleLocalWrite(int i);void handleLocalRead(int i);void handleCloseFromLocal(int i);void handleCloseFromRemote(int i);void handleAccept(int i);void openLocalFd(int se, int i);int getAddress(char *host, struct in_addr *iaddr);void selectPass(void) { int i; fd_set readfds, writefds; FD_ZERO(&readfds); FD_ZERO(&writefds); /* Server sockets */ for (i = 0; (i < seTotal); i++) { if (seFds[i] != INVALID_SOCKET) { FD_SET(seFds[i], &readfds); } } /* Connection sockets */ for (i = 0; (i < coTotal); i++) { if (coClosed[i]) { continue; } if (coClosing[i]) { if (!reClosed[i]) { FD_SET(reFds[i], &writefds); } if (!loClosed[i]) { FD_SET(loFds[i], &writefds); } } /* Get more input if we have room for it */ if ((!reClosed[i]) && (coInputRPos[i] < bufferSpace)) { FD_SET(reFds[i], &readfds); } /* Send more output if we have any */ if ((!reClosed[i]) && (coOutputWPos[i] < coOutputRPos[i])) { FD_SET(reFds[i], &writefds); } /* Accept more output from the local server if there's room */ if ((!loClosed[i]) && (coOutputRPos[i] < bufferSpace)) { FD_SET(loFds[i], &readfds); } /* Send more input to the local server if we have any */ if ((!loClosed[i]) && (coInputWPos[i] < coInputRPos[i])) { FD_SET(loFds[i], &writefds); } } select(maxfd + 1, &readfds, &writefds, 0, 0); for (i = 0; (i < seTotal); i++) { if (seFds[i] != -1) { if (FD_ISSET(seFds[i], &readfds)) { handleAccept(i); } } } for (i = 0; (i < coTotal); i++) { if (coClosed[i]) { continue; } if (!reClosed[i]) { if (FD_ISSET(reFds[i], &readfds)) { handleRemoteRead(i); } } if (!reClosed[i]) { if (FD_ISSET(reFds[i], &writefds)) { handleRemoteWrite(i); } } if (!loClosed[i]) { if (FD_ISSET(loFds[i], &readfds)) { handleLocalRead(i); } } if (!loClosed[i]) { if (FD_ISSET(loFds[i], &writefds)) { handleLocalWrite(i); } } if (loClosed[i] && reClosed[i]) { coClosed[i] = 1; } }}void handleRemoteRead(int i){ int got; if (bufferSpace == coInputRPos[i]) { return; } got = recv(reFds[i], coInput[i] + coInputRPos[i], bufferSpace - coInputRPos[i], 0); if (got == 0) { /* Prepare for closing */ handleCloseFromRemote(i); return; } if (got < 0) { if (GetLastError() == WSAEWOULDBLOCK) { return; } if (GetLastError() == WSAEINPROGRESS) { return; } handleCloseFromRemote(i); return; } coBytesInput[i] += got; coInputRPos[i] += got;}void handleRemoteWrite(int i){ int got; if (coClosing[i] && (coOutputWPos[i] == coOutputRPos[i])) { reClosed[i] = 1; coClosed[i] = 1; PERROR("rinetd: local closed and no more output"); log(i, coSe[i], logDone | coLog[i]); closesocket(reFds[i]); return; } got = send(reFds[i], coOutput[i] + coOutputWPos[i], coOutputRPos[i] - coOutputWPos[i], 0); if (got < 0) { if (GetLastError() == WSAEWOULDBLOCK) { return; } if (GetLastError() == WSAEINPROGRESS) { return; } handleCloseFromRemote(i); return; } coOutputWPos[i] += got; if (coOutputWPos[i] == coOutputRPos[i]) { coOutputWPos[i] = 0; coOutputRPos[i] = 0; } coBytesOutput[i] += got;}void handleLocalRead(int i){ int got; if (bufferSpace == coOutputRPos[i]) { return; } got = recv(loFds[i], coOutput[i] + coOutputRPos[i], bufferSpace - coOutputRPos[i], 0); if (got == 0) { handleCloseFromLocal(i); return; } if (got < 0) { if (GetLastError() == WSAEWOULDBLOCK) { return; } if (GetLastError() == WSAEINPROGRESS) { return; } handleCloseFromLocal(i); return; } coOutputRPos[i] += got;}void handleLocalWrite(int i){ int got; if (coClosing[i] && (coInputWPos[i] == coInputRPos[i])) { loClosed[i] = 1; coClosed[i] = 1; PERROR("remote closed and no more input"); log(i, coSe[i], logDone | coLog[i]); closesocket(loFds[i]); return; } got = send(loFds[i], coInput[i] + coInputWPos[i], coInputRPos[i] - coInputWPos[i], 0); if (got < 0) { if (GetLastError() == WSAEWOULDBLOCK) { return; } if (GetLastError() == WSAEINPROGRESS) { return; } handleCloseFromLocal(i); return; } coInputWPos[i] += got; if (coInputWPos[i] == coInputRPos[i]) { coInputWPos[i] = 0; coInputRPos[i] = 0; }}void handleCloseFromLocal(int i){ int arg; coClosing[i] = 1; /* The local end fizzled out, so make sure we're all done with that */ PERROR("close from local"); closesocket(loFds[i]); loClosed[i] = 1; if (!reClosed[i]) {#ifndef LINUX #ifndef WIN32
/* Now set up the remote end for a polite closing */ /* Request a low-water mark equal to the entire output buffer, so the next write notification tells us for sure that we can close the socket. */ arg = 1024; setsockopt(reFds[i], SOL_SOCKET, SO_SNDLOWAT, &arg, sizeof(arg));
#endif /* WIN32 */#endif /* LINUX */ coLog[i] = logLocalClosedFirst; } }void handleCloseFromRemote(int i){ int arg; coClosing[i] = 1; /* The remote end fizzled out, so make sure we're all done with that */ PERROR("close from remote"); closesocket(reFds[i]); reClosed[i] = 1; if (!loClosed[i]) {#ifndef LINUX
#ifndef WIN32 /* Now set up the local end for a polite closing */ /* Request a low-water mark equal to the entire output buffer, so the next write notification tells us for sure that we can close the socket. */ arg = 1024; setsockopt(loFds[i], SOL_SOCKET, SO_SNDLOWAT, &arg, sizeof(arg));
#endif /* WIN32 */#endif /* LINUX */ loClosed[i] = 0; coLog[i] = logRemoteClosedFirst; }}void refuse(int index, int logCode);void handleAccept(int i){ struct sockaddr addr; struct sockaddr_in *sin; unsigned char address[4]; char addressText[64]; int j; int addrlen; int index = -1; int o; SOCKET nfd; addrlen = sizeof(addr); nfd = accept(seFds[i], &addr, &addrlen); if (nfd == INVALID_SOCKET) { log(-1, i, logAcceptFailed); return; }#ifndef WIN32
if (nfd > maxfd) { maxfd = nfd; }#endif /* WIN32 */
j = 1; ioctlsocket(nfd, FIONBIO, &j);
j = 0;#ifndef WIN32
setsockopt(nfd, SOL_SOCKET, SO_LINGER, &j, sizeof(j));#endif
for (j = 0; (j < coTotal); j++) { if (coClosed[j]) { index = j; break; } } if (index == -1) { o = coTotal; coTotal *= 2; if (!SAFE_REALLOC(&reFds, sizeof(int) * o, sizeof(SOCKET) * coTotal)) { goto shortage; } if (!SAFE_REALLOC(&loFds, sizeof(int) * o,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -