Mercurial > dropbear
diff svr-main.c @ 309:474c1a700b67 ucc-axis-hack
add inetd server mode
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 26 Mar 2006 08:26:39 +0000 |
parents | 973fccb59ea4 |
children |
line wrap: on
line diff
--- a/svr-main.c Sat Mar 25 18:35:35 2006 +0000 +++ b/svr-main.c Sun Mar 26 08:26:39 2006 +0000 @@ -40,8 +40,16 @@ #ifdef NON_INETD_MODE static void main_noinetd(); #endif +#ifdef INETD_SERVER_MODE +static void main_inetd_server(); +#endif static void commonsetup(); +static void blank_dropbear_log(int priority, const char* format, va_list param) +{ + return; +} + #if defined(DBMULTI_dropbear) || !defined(DROPBEAR_MULTI) #if defined(DBMULTI_dropbear) && defined(DROPBEAR_MULTI) int dropbear_main(int argc, char ** argv) @@ -55,6 +63,13 @@ /* get commandline options */ svr_getopts(argc, argv); +#ifdef INETD_SERVER_MODE + if (svr_opts.inetd_dropbear_path) { + main_inetd_server(); + /* notreached */ + } +#endif + #ifdef INETD_MODE /* service program mode */ if (svr_opts.inetdmode) { @@ -90,7 +105,7 @@ /* In case our inetd was lax in logging source addresses */ addrstring = getaddrstring(&remoteaddr, 1); - dropbear_log(LOG_INFO, "Child connection from %s", addrstring); + dropbear_log(LOG_INFO, "Child inetd connection from %s", addrstring); /* Don't check the return value - it may just fail since inetd has * already done setsid() after forking (xinetd on Darwin appears to do @@ -323,6 +338,153 @@ } #endif /* NON_INETD_MODE */ +#ifdef INETD_SERVER_MODE +void main_inetd_server() { + fd_set fds; + struct timeval seltimeout; + unsigned int i; + int val; + int maxsock = -1; + int listensocks[MAX_LISTEN_ADDR]; + size_t listensockcount = 0; + FILE *pidfile = NULL; + + int childsock; + + /* fork */ + if (svr_opts.forkbg) { + int closefds = 0; +#ifndef DEBUG_TRACE + if (!svr_opts.usingsyslog) { + closefds = 1; + } +#endif + if (daemon(0, closefds) < 0) { + dropbear_exit("Failed to daemonize: %s", strerror(errno)); + } + } + + commonsetup(); + + /* should be done after syslog is working */ + if (svr_opts.forkbg) { + dropbear_log(LOG_INFO, "Running in background"); + } else { + dropbear_log(LOG_INFO, "Not forking"); + } + + /* create a PID file so that we can be killed easily */ + pidfile = fopen(DROPBEAR_PIDFILE, "w"); + if (pidfile) { + fprintf(pidfile, "%d\n", getpid()); + fclose(pidfile); + } + + /* Set up the listening sockets */ + listensockcount = listensockets(listensocks, MAX_LISTEN_ADDR, &maxsock); + if (listensockcount == 0) + { + dropbear_exit("No listening ports available."); + } + + /* incoming connection select loop */ + for(;;) { + + FD_ZERO(&fds); + + seltimeout.tv_sec = 60; + seltimeout.tv_usec = 0; + + /* listening sockets */ + for (i = 0; i < listensockcount; i++) { + FD_SET(listensocks[i], &fds); + } + + val = select(maxsock+1, &fds, NULL, NULL, &seltimeout); + + if (exitflag) { + unlink(DROPBEAR_PIDFILE); + dropbear_exit("Terminated by signal"); + } + + if (val == 0) { + /* timeout reached */ + continue; + } + + if (val < 0) { + if (errno == EINTR) { + continue; + } + dropbear_exit("Listening socket error"); + } + + /* handle each socket which has something to say */ + for (i = 0; i < listensockcount; i++) { + + struct sockaddr_storage remoteaddr; + socklen_t remoteaddrlen = 0; + pid_t fork_ret = 0; + + if (!FD_ISSET(listensocks[i], &fds)) + continue; + + remoteaddrlen = sizeof(remoteaddr); + childsock = accept(listensocks[i], + (struct sockaddr*)&remoteaddr, &remoteaddrlen); + + if (childsock < 0) { + /* accept failed */ + continue; + } + + fork_ret = fork(); + if (fork_ret < 0) { + dropbear_log(LOG_WARNING, "error forking: %s", strerror(errno)); + goto out; + + } else if (fork_ret > 0) { + /* parent */ + } else { + + char * argv[3]; + + /* child */ + + if (setsid() < 0) { + dropbear_exit("setsid: %s", strerror(errno)); + } + + /* make sure we close sockets */ + for (i = 0; i < listensockcount; i++) { + m_close(listensocks[i]); + } + + close(STDIN_FILENO); + close(STDOUT_FILENO); + //close(STDERR_FILENO); + + dup2(childsock, STDIN_FILENO); + dup2(childsock, STDOUT_FILENO); + + argv[0] = "dropbear"; + argv[1] = "-i"; + argv[2] = NULL; + + execv(svr_opts.inetd_dropbear_path, argv); + dropbear_exit("failed to fork inetd dropbear"); + + } +out: + /* This section is important for the parent too */ + m_close(childsock); + } + + } /* for(;;) loop */ + + /* don't reach here */ +} +#endif /* INETD_SERVER_MODE */ /* catch + reap zombie children */ static void sigchld_handler(int UNUSED(unused)) { @@ -383,7 +545,7 @@ * otherwise we might end up blatting error messages to the socket */ loadhostkeys(); - seedrandom(); + seedrandom(); } /* Set up listening sockets for all the requested ports */