/* * * Thu Oct 28 14:26:43 CEST 2010 * * :set tabstop=4 * */ static char __ident[] = "@(#)SPDsoft, Thu Oct 28 14:26:43 CEST 2010"; #define VERS_STR ((char*)&__ident[4]) #include #include #include /* atoi */ #include #if defined(__MACH__) && defined(__APPLE__) #include #endif #include /* getpid */ #include #include #include #include #include #include #include #include #ifdef __linux__ #include #else #include #endif #include #include #include #include #include #define BS 4096 #ifdef __sgi # define HAVE_DAEMONIZE #endif #ifdef __linux__ # define HAVE_DAEMON # define _DF_NOCHDIR 1 # define _daemonize(a,b,c,d) daemon((a),0) # define _POSIX_SIGNALS # define NOBODY 99 # define NOGROUP 99 #else # ifndef HAVE_DAEMONIZE /* _daemonize(3C) flags */ # define _DF_NOFORK 0x1 /* don't fork */ # define _DF_NOCHDIR 0x2 /* don't chdir to / */ # define _DF_NOCLOSE 0x4 /* close no files */ int my_daemonize(int flags, int fd1, int fd2, int fd3); # define _daemonize my_daemonize # define MY_DAEMONIZE # endif # define NOBODY 60001 # define NOGROUP 60001 #endif #define HAVE_SETSID 1 /* irix, linux, solaris */ #define HAVE_STRERROR 1 #ifndef HAVE_STRERROR # define strerror(e) sys_errlist[(e)] #endif #ifndef _POSIX_SIGNALS #ifndef _SYSV_SIGNALS # define _BSD_SIGNALS #endif #ifdef _BSD_SIGNALS # define sigset signal #endif #endif #ifndef DEFAULT_TPORT # define DEFAULT_TPORT 8001 #endif typedef struct { unsigned int port; int debug; char *bindh; char *logfile; FILE *f; } prefs_struct; prefs_struct gprefs; int s; int done; /* * Prototypes */ void clean( int i ); void debug_msg(const char *fmt, ...); void log_msg(const char *fmt, ...); void debug_msg(const char *fmt, ...) { va_list vl; if (gprefs.debug && ( NULL != gprefs.f)) { va_start(vl,fmt); vfprintf(gprefs.f,fmt,vl); va_end(vl); fflush(gprefs.f); } } void log_msg(const char *fmt, ...) { va_list vl; if ( NULL != gprefs.f) { va_start(vl,fmt); vfprintf(gprefs.f,fmt,vl); va_end(vl); fflush(gprefs.f); } } int main(int argc, char *argv[]) { long nbytes; int sockfd; int queue; struct sockaddr_in server, client; #ifdef __linux__ socklen_t clientlen=sizeof(client); #else int clientlen=sizeof(client); #endif char buf[BS]; int reuse=1; time_t timer; int option; #ifdef _POSIX_SIGNALS struct sigaction sigact; /* Signal action */ #endif gprefs.port=DEFAULT_TPORT; gprefs.debug=0; gprefs.logfile=NULL; gprefs.bindh=NULL; gprefs.f=stderr; while ( (option=getopt(argc,argv,"hvdl:b:p:")) != EOF ) { switch(option) { case 'b': gprefs.bindh = optarg; break; case 'l': gprefs.logfile = optarg; break; case 'd': gprefs.debug = 1; break; case 'p': gprefs.port = (unsigned int) atoi(optarg); break; case 'v': fprintf(stdout, "%s\n",VERS_STR); exit(0); break; case 'h': default: fprintf(stdout, "Use: %s [-hdv] [-l log] [-b bind] [-p port]\n", argv[0]); exit(0); } } memset(&server,0,sizeof(server)); if ( !gprefs.debug ) { if ( -1 == _daemonize(_DF_NOCHDIR, gprefs.f != NULL ? fileno(gprefs.f) : -1, -1,-1)) perror("Can't daemonize"); } server.sin_family = AF_INET; server.sin_port = htons(gprefs.port); server.sin_addr.s_addr = htonl(INADDR_ANY); if (gprefs.bindh != NULL ) server.sin_addr.s_addr = inet_addr(gprefs.bindh); queue=1; /* Set up a signal handler for SIGINT. The signal is sent to the * process when the user presses c. */ #ifdef _POSIX_SIGNALS sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigact.sa_handler = clean; if ( (sigaction(SIGTERM, &sigact, NULL) != 0) || (sigaction(SIGINT, &sigact, NULL) != 0) ) perror("sigaction(SIGINT) failed"); #else if ( ( SIG_ERR == sigset(SIGTERM, clean)) || ( SIG_ERR == sigset(SIGINT, clean)) ) perror("signal"); #endif debug_msg("open socket %d\n", s); if ( (s=socket(AF_INET,SOCK_STREAM,0)) == -1 ) { perror("socket"); exit(1); } if (setsockopt(s, SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(int)) == -1) { perror("setsockopt"); } debug_msg("bind to %s\n", inet_ntoa(server.sin_addr)); if( bind( s, (struct sockaddr *)&server, sizeof(server)) != 0 ) { perror("bind"); exit(1); } if ( NULL != gprefs.logfile ) { if ( NULL == ( gprefs.f = fopen(gprefs.logfile, "wb"))) { perror(optarg); gprefs.logfile = NULL; } } done=0; setgroups(0, NULL); if (-1==setegid(NOBODY)) perror("setegid"); if (-1==setgid(NOGROUP)) perror("setgid"); if (-1==setuid(NOBODY)) perror("setuid"); if ( listen( s, queue ) != 0 ) { perror("listen"); exit(1); } for(;!done; ) { debug_msg("%d accepting\n", getpid()); if( (sockfd = accept(s,(struct sockaddr *)&client,&clientlen)) < 0 ) if ( errno != EINTR ) { perror("accept"); break; } else continue; time(&timer); if ( (0==strcmp(inet_ntoa(client.sin_addr),"155.210.152.20")) || (0==strcmp(inet_ntoa(client.sin_addr),"155.210.152.24")) ) { debug_msg("accepted from %s\n", inet_ntoa(client.sin_addr)); } else { log_msg("REJECTED from %s - %s", inet_ntoa(client.sin_addr), ctime(&timer) ); shutdown(sockfd,2); close(sockfd); sockfd=0; continue; } nbytes = recv(sockfd,buf,sizeof(buf),0); buf[nbytes]=0x00; { char cmd[BS]; FILE *cmdf; size_t n,m; m=strlen(buf); for (n=0; n 0 ) { _exit(0); } #if HAVE_SETSID setsid(); #endif if ( -1 == (status = fork())) { perror("cant fork again"); exit(1); } else if ( status > 0 ) { _exit(0); } } #ifdef TIOCNOTTY if ( 0 < (fd = open("/dev/tty", O_RDWR))) { if (ioctl(fd, TIOCNOTTY, NULL) < 0) { perror("can't disassociate from the terminal"); status=-1; } close(fd); } #endif /* TIOCNOTTY */ if (!(flags & _DF_NOCHDIR)) { if (chdir("/.") < 0) { perror("can't chdir to /."); status=-1; } } if (!(flags & _DF_NOCLOSE)) { long l; int i; l=sysconf(_SC_OPEN_MAX); while(l-->0) { if ((l!=fd1)&&(l!=fd2)&&(l!=fd3)) close(l); } if ( -1 == ( i = open( "/dev/null", O_RDWR))) { perror("/dev/null"); status=-1; } else { if ((1!=fd1)&&(1!=fd2)&&(1!=fd3)) dup(i); if ((2!=fd1)&&(2!=fd2)&&(2!=fd3)) dup(i); } } return(status); } #endif