/* * Un faux daemon. * * Copyright (c) 1999 Association CRANS. * * Auteur: Olivier Saut * * gvim c'est vraiment le pied :-) * * A faire : detecter le premier paquet SYN. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef LINUX #include #endif #define kZamok_Tourne 1 #define kPORT 514 /* Port de rshd */ #define kMaxDaemonChildren 10 int nbrFils; int daemon_init(void) { pid_t pid; if((pid = fork())<0) return (-1); else if (pid !=0) { (void)fprintf(stdout,"beastie launched : %d\n",pid); exit(0); } setsid(); chdir("/"); umask(0); return(0); } /* Attention subtil (waitpid plutot que wait) :-) */ void zombie(int signo) { pid_t pid; int stat; while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) nbrFils--; return; } void sigterm(int signo) { syslog(LOG_NOTICE,"beastie killed by SIGTERM."); closelog(); exit(EXIT_SUCCESS); } int main(int argc, char *argv[]){ int serv_sock, client_sock, cli_len; struct sockaddr_in serv_addr, cli_addr; struct hostent *cli_ent; char *clientname,*message; int PORT; pid_t pid; sig_t previous_handler; char buffer[1024]; if(argc>1) PORT=atoi(argv[1]); else PORT=kPORT; if(setuid(getuid())) { perror("Setuid."); exit(EXIT_FAILURE); } /* On se daemonize */ if(daemon_init()) { perror("Initialize as daemon."); exit(EXIT_FAILURE); } /* Pour éviter les zombies (vade retro...) */ previous_handler = signal(SIGCHLD,(sig_t)zombie); if(previous_handler==SIG_ERR) { perror("Installing SIGCHLD handler"); exit(EXIT_FAILURE); } /* Pour détecter le SIGTERM */ previous_handler = signal(SIGTERM,(sig_t)sigterm); if(previous_handler==SIG_ERR) { perror("Installing SIGTERM handler"); exit(EXIT_FAILURE); } nbrFils=0; #ifndef LINUX setproctitle("ecoute le port %d",PORT); #endif openlog("beastie", LOG_PID|LOG_CONS,LOG_LOCAL2); serv_sock = socket(AF_INET, SOCK_STREAM, 0); if (serv_sock < 0) { perror("Creating server socket."); exit(EXIT_FAILURE); } /* On remplit la structure */ bzero((char *) &serv_addr, sizeof (serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(PORT); /* Et on lie la socket au port */ if (bind(serv_sock, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) { perror("Binding server socket."); exit(EXIT_FAILURE); } listen(serv_sock,5); while(kZamok_Tourne) { cli_len = sizeof (cli_addr); bzero((char *) &cli_addr, sizeof (cli_addr)); client_sock = accept(serv_sock, (struct sockaddr *) &cli_addr, &cli_len); if (client_sock < 0) { perror("Accepting connection on server socket."); break; } /* On forke, on traite la requete dans le fils */ /* Evaluation paresseuse */ if((nbrFils++ < kMaxDaemonChildren) && ((pid=fork())==0) ) { close(serv_sock); clientname=inet_ntoa(cli_addr.sin_addr); /* On recupere le nom */ /* Hehe t'es loggue mon pote */ if(strcmp(clientname, "127.0.0.1")) { if (!((cli_ent= gethostbyaddr((char *)&cli_addr.sin_addr.s_addr, sizeof (u_long), AF_INET)) == (struct hostent *)0)) { snprintf(buffer,1023, "Tentative de connexion de %s au port %d.",cli_ent->h_name,PORT); syslog(LOG_NOTICE,buffer ); } else { snprintf(buffer,1023, "Tentative de connexion de %s au port %d.",clientname,PORT); syslog(LOG_NOTICE,buffer); } } close(client_sock); exit(0); } /* Fin du fork */ close(client_sock); } closelog(); close(serv_sock); exit( 0); }