Messages in this thread | | | From | "Mike Goldman" <> | Subject | Re: Opening 5000 file descriptors in linux?? | Date | Tue, 11 May 1999 12:58:50 -0400 |
| |
/* * SHIMD - A simple multi-forking socket-redirecting daemon * Copyright (C) 1996 by Mike Goldman <whig@by.net> * * This program is released under the GNU General Public License */
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> #include <signal.h>
int NeedToDie = 0, sid = 0; void onsig(int sig) { if (sig == SIGTERM && !NeedToDie) { NeedToDie = 1; signal(sig, onsig); kill(-sid, sig); } else signal(sig, onsig); }
void ShimCopy(int Dst, int Src) { char buf[1024]; int got = read(Src, buf, sizeof (buf)); if (got > 0) write(Dst, buf, got); else if (errno != EINTR) exit(0); }
void Shim(int Socket, u_short ServerPort) { int Server = 0; struct sockaddr sockaddr; int len = sizeof (sockaddr); struct sockaddr_in inaddr; fd_set Select; int Client = accept(Socket, NULL, NULL); if (Client < 0) return; if (getsockname(Client, &sockaddr, &len) < 0) goto EndShim; if ((Server = socket(AF_INET, SOCK_STREAM, 0)) < 0) goto EndShim; bzero(&inaddr, sizeof (inaddr)); inaddr.sin_family = AF_INET; inaddr.sin_addr.s_addr = ((struct sockaddr_in *)&sockaddr)->sin_addr.s_addr; inaddr.sin_port = htons(ServerPort); if (connect(Server, (void *)&inaddr, sizeof (inaddr)) < 0) goto EndShim; if (fork()) goto EndShim;
close (Socket); while (!NeedToDie) { FD_ZERO(&Select); FD_SET(Server, &Select); FD_SET(Client, &Select); if (select(((Server > Client)? Server : Client) + 1, &Select, NULL, NULL, NULL) < 0) continue; if (FD_ISSET(Server, &Select)) ShimCopy(Client, Server); if (FD_ISSET(Client, &Select)) ShimCopy(Server, Client); } exit(0);
EndShim: close(Client); if (Server) close (Server); }
#define MAXSOCKS 200 void Process(u_short Servic, u_long Range1, u_long Range2, u_short thisServer) { struct sockaddr_in inaddr; int n; static int Sockets = 0; static int *Socket = NULL; static u_short *Server = NULL; static int Listen; static fd_set Select, Selected; if (Servic) for (; Range1 <= Range2; Range1++) { Socket = realloc(Socket, (Sockets+1) * sizeof (*Socket)); if (Sockets >= MAXSOCKS || (Socket[Sockets] = socket(AF_INET, SOCK_STREAM, 0)) < 0) { Range1--; if (!fork()) break; while (Sockets) close(Socket[Sockets--]); continue; } n = 1; setsockopt(Socket[Sockets], SOL_SOCKET, SO_REUSEADDR, &n, sizeof (n)); bzero(&inaddr, sizeof (inaddr)); inaddr.sin_family = AF_INET; inaddr.sin_port = htons(Servic); inaddr.sin_addr.s_addr = htonl(Range1); bind(Socket[Sockets], (void *)&inaddr, sizeof (inaddr)); listen(Socket[Sockets], 5); if (!Sockets) { FD_ZERO(&Select); Listen = 0; } FD_SET(Socket[Sockets], &Select); if (Socket[Sockets] >= Listen) Listen = Socket[Sockets]+1; Server = realloc(Server, (Sockets+1) * sizeof (*Server)); Server[Sockets] = thisServer; Sockets++; } if (Range1 > Range2) return; while (!NeedToDie) { Selected = Select; if (select(Listen, &Selected, NULL, NULL, NULL) <= 0) continue; for (n = 0; n < Sockets; n++) if (FD_ISSET(Socket[n], &Selected)) Shim(Socket[n], Server[n]); } }
void main(void) { char line[255], *delim = "\t\r\n "; FILE *fp = fopen("/etc/shimd.conf", "r"); if (fp == NULL || fork()) return; sid = setsid(); signal(SIGCHLD, SIG_IGN); signal(SIGTERM, onsig);
while (fgets(line, sizeof(line), fp)) { char *szServic = strtok(line, delim); u_short usServic; char *szRange1 = strtok(NULL, delim); u_long ulRange1; char *szRange2 = strtok(NULL, delim); u_long ulRange2; char *szServer = strtok(NULL, delim); u_short usServer; if (!szServic || *szServic == '#' || !szRange1 || !szRange2 || !szServer) continue; usServic = atoi(szServic); ulRange1 = ntohl(inet_addr(szRange1)); ulRange2 = ntohl(inet_addr(szRange2)); usServer = atoi(szServer); if (!usServic || !usServer || ulRange1 == (u_long)-1L || ulRange2 == (u_long)-1L) continue; if (ulRange1 > ulRange2) { ulRange1 ^= ulRange2; ulRange2 ^= ulRange1; ulRange1 ^= ulRange2; } Process(usServic, ulRange1, ulRange2, usServer); } if (!NeedToDie) Process(0,0,0,0); }
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |