2 * (c) Copyright 1992 by Panagiotis Tsirigotis
3 * (c) Sections Copyright 1998-2001 by Rob Braun
4 * All rights reserved. The file named COPYRIGHT specifies the terms
5 * and conditions for redistribution.
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
19 #ifdef HAVE_SYS_FILE_H
38 #define NEW_SERVER() NEW( struct server )
39 #define FREE_SERVER( serp ) FREE( serp )
43 #define do_fork() fork()
49 * 3 out of 4 times the do_fork() will fail
51 #define do_fork() ( random() & 0x11 ) ? ( errno = EAGAIN, -1 ) : fork()
52 #endif /* DEBUG_RETRY */
56 * Allocate a server, initialize it from init_serp, and insert it in the server
59 struct server *server_alloc( const struct server *init_serp )
62 const char *func = "server_alloc" ;
67 out_of_memory( func ) ;
71 if ( pset_add( SERVERS(ps), serp ) == NULL )
73 msg( LOG_CRIT, func, "couldn't insert server in server table" ) ;
79 *serp = *init_serp ; /* initialize it */
80 SVC_HOLD( SERVER_SERVICE(serp) ) ;
86 void server_release( struct server *serp )
88 struct service *sp = SERVER_SERVICE( serp ) ;
89 int count = SVC_RELE( sp ) ;
91 pset_remove(SERVERS(ps), serp);
93 if( ! SC_IS_SPECIAL( SVC_CONF( sp ) ) )
94 pset_remove( SERVICES( ps ), sp ) ;
104 * If a service is internal and does not require forking a process:
105 * - if it accepts connections, we put the accepted connection
106 * in non-blocking mode to avoid a possible block on
108 * - the log flags that have to do with the server exiting are
109 * ignored (i.e. nothing is logged).
110 * - it can be identified in the log because the server pid is 0.
112 static void server_internal( struct server *serp )
114 struct service *sp = SERVER_SERVICE(serp) ;
115 const char *func = "server_internal" ;
117 SERVER_PID(serp) = 0 ;
118 if ( SVC_ACCEPTS_CONNECTIONS( sp ) &&
119 fcntl( SERVER_FD( serp ), F_SETFL, FNDELAY ) == -1 )
121 msg( LOG_ERR, func, "%s: fcntl F_SETFL failed: %m", SVC_ID( sp ) ) ;
124 svc_log_success( sp, SERVER_CONNECTION(serp), SERVER_PID(serp) ) ;
125 SVC_INTERNAL( sp, serp ) ;
130 * Attempt to start a server for service 'sp' to handle
133 * OK: if a server is started or a retry attempt is scheduled
134 * FAILED: otherwise (a log entry is also made)
136 status_e server_run( struct service *sp, connection_s *cp )
138 struct server server ;
139 struct server *serp = NULL;
140 const char *func = "server_run" ;
144 server.svr_conn = cp ;
146 if ( ! SVC_FORKS( sp ) )
148 * SG - Added this check so that internal services get the
149 * same protection that external services get. This is
150 * mandatory for the sensor patch to work.
153 if (svc_child_access_control( sp, cp ) == OK)
154 server_internal( &server ) ;
156 if ( SVC_WAITS( sp ) )
160 if ( SVC_WAITS( sp ) )
166 * Insert new struct server in server table first, to avoid the
167 * possibility of running out of memory *after* the fork.
169 serp = server_alloc( &server ) ;
173 if ( server_start( serp ) == OK )
180 /* server will be removed in server_release() */
183 * Currently, fork failures are the only reason for retrying.
184 * There is no retry if we exceed the max allowed number of fork failures
186 if ( ! SERVER_FORKLIMIT( serp ) && SVC_RETRY( sp ) )
188 if ( schedule_retry( serp ) == OK )
191 msg( LOG_ERR, func, "Retry failure for %s service", SVC_ID( sp ) ) ;
194 svc_log_failure( sp, cp, AC_FORK ) ;
196 server_release( serp ) ;
202 * Try to fork a server process.
203 * Actually, we won't fork if tcpmux_child is set, becuase we have
204 * already forked to keep the xinetd parent from blocking on the
205 * read of the service name.
207 status_e server_start( struct server *serp )
209 struct service *sp = SERVER_SERVICE(serp) ;
210 const char *func = "server_start" ;
213 msg( LOG_DEBUG, func, "Starting service %s", SC_NAME( SVC_CONF( sp ) ) );
214 SERVER_LOGUSER(serp) = SVC_LOGS_USERID_ON_SUCCESS( sp ) ;
216 SERVER_PID(serp) = do_fork() ;
218 switch ( SERVER_PID(serp) )
221 ps.rws.env_is_valid = FALSE ;
222 child_process( serp ) ;
224 msg( LOG_ERR, func, "INTERNAL ERROR: child_process returned" ) ;
229 msg( LOG_ERR, func, "%s: fork failed: %m", SVC_ID( sp ) ) ;
230 SERVER_FORK_FAILURES(serp)++ ;
234 (void) time( &SERVER_STARTTIME(serp) ) ;
235 SVC_INC_RUNNING_SERVERS( sp ) ;
238 * Log the start of another server (if it is not an interceptor).
239 * Determine if the server writes to the log (because in that case
240 * we will have to check the log size).
242 if ( ! SVC_IS_INTERCEPTED( sp ) )
243 svc_log_success( sp, SERVER_CONNECTION(serp), SERVER_PID(serp) ) ;
245 SERVER_WRITES_TO_LOG(serp) = SVC_IS_LOGGING( sp ) ;
246 SERVER_WRITES_TO_LOG(serp) |= SERVER_LOGUSER(serp) ;
252 void server_dump( const struct server *serp, int fd )
254 const struct service *sp = SERVER_SERVICE(serp) ;
256 Sprint( fd, "%s server\n", SVC_ID( sp ) ) ;
257 Sprint( fd, "pid = %d\n", SERVER_PID(serp) ) ;
258 Sprint( fd, "start_time = %s", ctime( &SERVER_STARTTIME(serp) ) ) ;
259 Sprint( fd, "Connection info:\n" ) ;
260 conn_dump( SERVER_CONNECTION(serp), fd ) ;
261 if ( SERVER_FORK_FAILURES(serp) )
262 Sprint( fd, "fork_failures = %d\n", SERVER_FORK_FAILURES(serp) ) ;
264 "log_remote_user = %s\n", SERVER_LOGUSER(serp) ? "YES" : "NO" ) ;
266 "writes_to_log = %s\n", SERVER_WRITES_TO_LOG(serp) ? "YES" : "NO" ) ;
267 Sputchar( fd, '\n' ) ;
273 * Invoked when a server dies, either because of a signal or in case of
276 void server_end( struct server *serp )
278 struct service *sp = SERVER_SERVICE(serp) ;
279 const char *func = "server_end" ;
281 if ( PROC_EXITED( SERVER_EXITSTATUS(serp) ) ||
282 PROC_SIGNALED( SERVER_EXITSTATUS(serp) ) )
284 const char *death_type = PROC_EXITED( SERVER_EXITSTATUS(serp) ) ? "exited"
288 struct service *conn_sp = CONN_SERVICE( SERVER_CONNECTION(serp) ) ;
291 msg( LOG_DEBUG, func,
292 "%s server %d %s", SVC_ID( sp ) , SERVER_PID(serp), death_type ) ;
294 msg( LOG_DEBUG, func,
295 "%s server %d running on behalf of service %s %s",
296 SVC_ID( sp ), SERVER_PID(serp), SVC_ID( conn_sp ), death_type ) ;
299 /* Added this for when accepting wait=yes services */
300 if( SVC_WAITS( sp ) )
301 FD_SET( SVC_FD( sp ), &ps.rws.socket_mask ) ;
303 svc_postmortem( sp, serp ) ;
304 server_release( serp ) ;
306 else if ( PROC_STOPPED( SERVER_EXITSTATUS(serp) ) )
307 msg( LOG_WARNING, func, "service %s: server with pid %d stopped",
308 SVC_ID( sp ), SERVER_PID(serp) ) ;
313 * Find the running server with the specified pid
315 struct server *server_lookup( pid_t pid )
319 for ( u = 0 ; u < pset_count( SERVERS( ps ) ) ; u++ )
321 register struct server *serp ;
323 serp = SERP( pset_pointer( SERVERS( ps ), u ) ) ;
324 if ( SERVER_PID(serp) == pid )