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/types.h>
11 #include <sys/socket.h>
17 #include <netinet/in.h>
19 #ifdef HAVE_RPC_PMAP_CLNT_H
21 #include <rpc/types.h>
24 #include <rpc/types.h>
28 #include <rpc/pmap_clnt.h>
37 #include "confparse.h"
45 static status_e readjust(struct service *sp,
46 struct service_config **new_conf_ptr) ;
47 static void swap_defaults(struct configuration *new_conf) ;
48 static void close_default_log(struct configuration *confp, xlog_h def_log);
50 #define SWAP( x, y, temp ) (temp) = (x), (x) = (y), (y) = (temp)
54 * Reconfigure the server by rereading the configuration file.
55 * Services may be added, deleted or have their attributes changed.
56 * All syslog output uses the LOG_NOTICE priority level (except for
59 void hard_reconfig( void )
62 struct service_config *nscp ;
63 struct configuration new_conf ;
65 unsigned new_services ;
66 unsigned old_services = 0 ;
67 unsigned dropped_services = 0 ;
68 xlog_h def_log = DEFAULT_LOG( ps );
69 const char *func = "hard_reconfig" ;
72 msg( LOG_NOTICE, func, "Starting reconfiguration" ) ;
74 if ( cnf_get( &new_conf ) == FAILED )
76 msg( LOG_WARNING, func, "reconfiguration failed" ) ;
80 iter = psi_create( SERVICES( ps ) ) ;
83 out_of_memory( func ) ;
84 cnf_free( &new_conf ) ;
88 /* After this call, new_conf's defaults point to the old one's defaults */
89 msg( LOG_NOTICE, func, "Swapping defaults" ) ;
90 swap_defaults( &new_conf ) ;
94 * Sconf: service configuration
95 * Lconf: list of service configurations
97 * Iterate over all existing services. If the service is included in the
98 * new Lconf, readjust its attributes (as a side-effect, the new service
99 * Sconf is removed from the new Lconf).
100 * Services not in the new Lconf are deactivated.
102 for ( osp = SP( psi_start( iter ) ) ; osp ; osp = SP( psi_next( iter ) ) )
104 char *sid = SVC_ID( osp ) ;
105 boolean_e drop_service ;
108 * Check if this service is in the new Lconf
109 * Notice that the service Sconf is removed from the new Lconf
110 * if it is found there.
112 if ( (nscp = cnf_extract( &new_conf, SVC_CONF( osp ) )) )
115 * The first action of readjust is to swap the service configuration
116 * with nscp. This is the reason for passing the address of nscp
117 * (so that on return nscp will *always* point to the old service
120 if ( readjust( osp, &nscp ) == OK )
125 else /* the readjustment failed */
132 if ( drop_service == YES )
135 * Procedure for disabling a service:
137 * a. Deactivate the service to prevent new connections
138 * b. Terminate running servers and cancel retry attempts, in case
141 svc_deactivate( osp ) ;
142 terminate_servers( osp ) ;
143 cancel_service_retries( osp ) ;
146 * Deactivate the service; the service will be deleted only
147 * if its reference count drops to 0.
149 /* Always remove the service, even if not all the children
150 * have been killed, or there are other references.
153 msg( LOG_NOTICE, func, "service %s deactivated", sid ) ;
154 if ( SVC_RELE( osp ) == 0 ) {
157 msg( LOG_ERR, func, "Errors deactivating service %s", sid ) ;
162 psi_destroy( iter ) ;
165 * All services have terminated by now, so close the old common logfile.
166 * remember that swap_defaults put the old defaults section in new_conf.
168 close_default_log( &new_conf, def_log ) ;
171 * At this point the new Lconf only contains services that were not
174 new_services = cnf_start_services( &new_conf ) ;
175 msg( LOG_NOTICE, func,
176 "Reconfigured: new=%d old=%d dropped=%d (services)",
177 new_services, old_services, dropped_services ) ;
179 if ( stayalive_option == 0 ) {
180 if ( ps.rws.available_services == 0 )
182 msg( LOG_CRIT, func, "No available services. Exiting" );
183 if ( ps.ros.pid_file ) {
184 unlink(ps.ros.pid_file);
190 cnf_free( &new_conf ) ;
194 static void swap_defaults( struct configuration *new_conf )
196 struct service_config *temp ;
198 DEFAULT_LOG_ERROR( ps ) = FALSE ;
199 DEFAULT_LOG( ps ) = NULL ;
200 SWAP( DEFAULTS( ps ), CNF_DEFAULTS( new_conf ), temp ) ;
204 static void close_default_log(struct configuration *confp, xlog_h def_log)
206 /* Close the common log file, if one was specified */
207 if ( def_log != NULL )
208 log_end( SC_LOG( CNF_DEFAULTS( confp ) ), def_log) ;
212 static void sendsig( struct server *serp, int sig )
214 char *sid = SVC_ID( SERVER_SERVICE( serp ) ) ;
215 pid_t pid = SERVER_PID( serp ) ;
216 const char *func = "sendsig" ;
219 * Always use a positive pid, because of the semantics of kill(2)
223 msg( LOG_WARNING, func, "Sending signal %d to %s server %d",
226 if ((sig == SIGTERM) || (sig == SIGKILL))
232 * We will try 4 seconds to TERM or KILL it. If it hasn't
233 * responded by 2.5 seconds, we will send a KILL to hasten
238 tv.tv_usec = 500000; /* half a second */
241 if( server_lookup(pid) == NULL )
246 int wret = waitpid(pid, NULL, WNOHANG);
254 /* May not have responded to TERM, send a KILL */
256 kill( pid, SIGKILL ) ;
258 /* Not dead yet, give some time. */
259 select(0, NULL, NULL, NULL, &tv);
263 * If it didn't die, expect problems rebinding to this port if
264 * a hard_reconfig is in process.
267 msg( LOG_ERR, func, "Server %d did not exit after SIGKILL",
269 /* no need to server_end() here. The killed process will generate
270 * a sigchld, which will invoke the signal handler, and clean things
276 msg( LOG_ERR, func, "Negative server pid = %d. Service %s", pid, sid ) ;
281 * Send signal sig to all running servers of service sp
283 static void deliver_signal( struct service *sp, int sig )
287 for ( u = 0 ; u < pset_count( SERVERS( ps ) ) ; u++ )
289 struct server *serp ;
291 serp = SERP( pset_pointer( SERVERS( ps ), u ) ) ;
292 if ( SERVER_SERVICE( serp ) == sp ) {
293 sendsig( serp, sig ) ;
294 if ( (sig == SIGTERM) || (sig == SIGKILL) )
302 * Terminate all servers of the specified service
304 void terminate_servers( struct service *sp )
306 int sig = SC_IS_INTERNAL( SVC_CONF( sp ) ) ? SIGTERM : SIGKILL ;
308 deliver_signal( sp, sig ) ;
312 static void stop_interception( struct service *sp )
314 deliver_signal( sp, INTERCEPT_SIG ) ;
318 * Stop logging. svc_activate starts logging and will leak a file
319 * descriptor and memory if this is not called prior.
321 static void stop_log( struct service *sp,
322 struct service_config *old_conf )
324 struct log *lp = SC_LOG( old_conf ) ;
326 if ( LOG_GET_TYPE( lp ) != L_NONE && SVC_IS_LOGGING( sp ) )
327 log_end( lp, SVC_LOG( sp ) ) ;
328 SVC_LOG( sp ) = NULL ;
332 * Stop any logging and restart if necessary.
333 * Note that this has the side-effect of using the new common log
334 * handle as it should.
336 static status_e restart_log( struct service *sp,
337 struct service_config *old_conf )
339 stop_log( sp, old_conf );
340 return( log_start( sp, &SVC_LOG( sp ) ) ) ;
345 * Unregister past versions, register new ones
346 * We do it the dumb way: first unregister; then register
347 * We try to be a little smart by checking if there has
348 * been any change in version numbers (if not, we do nothing).
349 * Also, we save the port number
351 static status_e readjust_rpc_service( struct service_config *old_scp,
352 struct service_config *new_scp )
355 uint16_t port = SC_PORT( old_scp ) ;
356 struct rpc_data *new_rdp = SC_RPCDATA( new_scp ) ;
357 struct rpc_data *old_rdp = SC_RPCDATA( old_scp ) ;
358 unsigned registered_versions = 0 ;
359 const char *func = "readjust_rpc_service" ;
362 SC_PORT( new_scp ) = SC_PORT( old_scp ) ;
364 if ( RD_MINVERS( old_rdp ) == RD_MINVERS( new_rdp ) &&
365 RD_MAXVERS( old_rdp ) == RD_MAXVERS( new_rdp ) )
368 for ( vers = RD_MINVERS( old_rdp ) ; vers <= RD_MAXVERS( old_rdp ) ; vers++ )
369 (void) pmap_unset( RD_PROGNUM( old_rdp ), vers ) ;
371 for ( vers = RD_MINVERS( new_rdp ) ; vers <= RD_MAXVERS( new_rdp ) ; vers++ )
372 if ( pmap_set( RD_PROGNUM( new_rdp ),
373 vers, SC_PROTOVAL( new_scp ), port ) )
374 registered_versions++ ;
377 "pmap_set failed. service=%s, program=%ld, version = %ld",
378 SC_ID( new_scp ), RD_PROGNUM( new_rdp ), vers ) ;
380 if ( registered_versions == 0 )
383 "No versions registered for RPC service %s", SC_ID( new_scp ) ) ;
385 * Avoid the pmap_unset
387 RD_MINVERS( new_rdp ) = RD_MAXVERS( new_rdp ) + 1 ;
390 #endif /* ! NO_RPC */
396 * Readjust service attributes.
398 * We assume that the following attributes are the same:
404 * Readjustment happens in 3 steps:
405 * 1) We swap the svc_conf fields
406 * This has the side-effect of free'ing the memory associated
407 * with the old service configuration when the new configuration
409 * 2) We readjust the fields that require some action to be taken:
412 * 3) We update the address control fields.
414 static status_e readjust( struct service *sp,
415 struct service_config **new_conf_ptr )
417 struct service_config *temp_conf ;
418 struct service_config *old_conf = SVC_CONF( sp ) ;
419 struct service_config *new_conf = *new_conf_ptr ;
420 char *sid = SVC_ID( sp ) ;
421 const char *func = "readjust" ;
423 msg( LOG_NOTICE, func, "readjusting service %s", sid ) ;
425 SWAP( SVC_CONF( sp ), *new_conf_ptr, temp_conf ) ;
427 if ( SC_IS_RPC( old_conf ) &&
428 readjust_rpc_service( old_conf, new_conf ) == FAILED )
432 * This is what happens if the INTERCEPT flag is toggled and an
433 * interceptor is running:
436 * Wait until the server dies (soft reconfig) or
437 * terminate the server (hard reconfig)
440 * Send a signal to the interceptor to tell it to stop intercepting
442 if ( SC_IS_INTERCEPTED( old_conf ) != SC_IS_INTERCEPTED( new_conf ) )
444 if ( SC_IS_INTERCEPTED( new_conf ) ) /* case 1 */
445 terminate_servers( sp ) ;
448 stop_interception( sp ) ;
449 msg( LOG_NOTICE, func, "Stopping interception for %s", sid ) ;
454 * See if the bind address was specified in both the old and new config,
455 * then if it changed, readjust the service. The algorithm is check to
456 * see if they are in the same address family, if so start a simple
457 * comparison based on the address family. If IPv4, the addresses can be
458 * compared directly, otherwise use the IPv6 macro. If they are not the
459 * same, terminate & restart the service.
461 if( (SC_BIND_ADDR(old_conf) != NULL) && (SC_BIND_ADDR(new_conf) != NULL) ) {
464 if ( SA(SC_BIND_ADDR(old_conf))->sa_family ==
465 SA(SC_BIND_ADDR(new_conf))->sa_family ) {
466 if ( SA(SC_BIND_ADDR(old_conf))->sa_family == AF_INET ) {
467 if ( SAIN(SC_BIND_ADDR(old_conf))->sin_addr.s_addr ==
468 SAIN(SC_BIND_ADDR(new_conf))->sin_addr.s_addr)
471 else if ( IN6_ARE_ADDR_EQUAL(
472 &SAIN6(SC_BIND_ADDR(old_conf))->sin6_addr,
473 &SAIN6(SC_BIND_ADDR(new_conf))->sin6_addr) )
478 terminate_servers( sp );
479 svc_deactivate( sp );
480 stop_log( sp, old_conf ); /* svc_activate re-starts logging */
486 /* If the service didn't have a bind address before, but does now,
487 * make sure the new bind directive takes effect.
489 if( (SC_BIND_ADDR(old_conf) == NULL) && (SC_BIND_ADDR(new_conf) != NULL) ) {
490 terminate_servers( sp );
492 stop_log( sp, old_conf ); /* svc_activate re-starts logging */
497 if( (SC_IPV4(old_conf) && SC_IPV6(new_conf)) ||
498 (SC_IPV6(old_conf) && SC_IPV4(new_conf)) ) {
499 terminate_servers( sp );
501 stop_log( sp, old_conf ); /* svc_activate re-starts logging */
506 return( restart_log( sp, old_conf ) ) ;