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. Terminate running servers and cancel retry attempts, in case
139
* b. Deactivate the service
141
terminate_servers( osp ) ;
142
cancel_service_retries( osp ) ;
145
* Deactivate the service; the service will be deleted only
146
* if its reference count drops to 0.
148
svc_deactivate( osp ) ;
149
msg( LOG_NOTICE, func, "service %s deactivated", sid ) ;
150
if ( SVC_RELE( osp ) == 0 )
153
msg( LOG_ERR, func, "Errors deactivating service %s", sid ) ;
158
psi_destroy( iter ) ;
161
* All services have terminated by now, so close the old common logfile.
162
* remember that swap_defaults put the old defaults section in new_conf.
164
close_default_log( &new_conf, def_log ) ;
167
* At this point the new Lconf only contains services that were not
170
new_services = cnf_start_services( &new_conf ) ;
171
msg( LOG_NOTICE, func,
172
"Reconfigured: new=%d old=%d dropped=%d (services)",
173
new_services, old_services, dropped_services ) ;
175
if ( stayalive_option == 0 ) {
176
if ( ps.rws.available_services == 0 )
178
msg( LOG_CRIT, func, "No available services. Exiting" );
179
if ( ps.ros.pid_file ) {
180
unlink(ps.ros.pid_file);
186
cnf_free( &new_conf ) ;
190
static void swap_defaults( struct configuration *new_conf )
192
struct service_config *temp ;
194
DEFAULT_LOG_ERROR( ps ) = FALSE ;
195
DEFAULT_LOG( ps ) = NULL ;
196
SWAP( DEFAULTS( ps ), CNF_DEFAULTS( new_conf ), temp ) ;
200
static void close_default_log(struct configuration *confp, xlog_h def_log)
202
/* Close the common log file, if one was specified */
203
if ( def_log != NULL )
204
log_end( SC_LOG( CNF_DEFAULTS( confp ) ), def_log) ;
208
static void sendsig( struct server *serp, int sig )
210
char *sid = SVC_ID( SERVER_SERVICE( serp ) ) ;
211
pid_t pid = SERVER_PID( serp ) ;
212
const char *func = "sendsig" ;
215
* Always use a positive pid, because of the semantics of kill(2)
219
msg( LOG_WARNING, func, "Sending signal %d to %s server %d",
222
if ((sig == SIGTERM) || (sig == SIGKILL))
228
* We will try 4 seconds to TERM or KILL it. If it hasn't
229
* responded by 2.5 seconds, we will send a KILL to hasten
234
tv.tv_usec = 500000; /* half a second */
237
int wret = waitpid(pid, NULL, WNOHANG);
244
/* May not have responded to TERM, send a KILL */
246
kill( pid, SIGKILL ) ;
248
/* Not dead yet, give some time. */
249
select(0, NULL, NULL, NULL, &tv);
253
* If it didn't die, expect problems rebinding to this port if
254
* a hard_reconfig is in process.
257
msg( LOG_ERR, func, "Server %d did not exit after SIGKILL",
260
struct server *tmp_serp;
261
if( (tmp_serp = server_lookup(pid)) != NULL ) {
262
server_end(tmp_serp);
268
msg( LOG_ERR, func, "Negative server pid = %d. Service %s", pid, sid ) ;
273
* Send signal sig to all running servers of service sp
275
static void deliver_signal( struct service *sp, int sig )
279
for ( u = 0 ; u < pset_count( SERVERS( ps ) ) ; u++ )
281
struct server *serp ;
283
serp = SERP( pset_pointer( SERVERS( ps ), u ) ) ;
284
if ( SERVER_SERVICE( serp ) == sp )
285
sendsig( serp, sig ) ;
291
* Terminate all servers of the specified service
293
void terminate_servers( struct service *sp )
295
int sig = SC_IS_INTERNAL( SVC_CONF( sp ) ) ? SIGTERM : SIGKILL ;
297
deliver_signal( sp, sig ) ;
301
static void stop_interception( struct service *sp )
303
deliver_signal( sp, INTERCEPT_SIG ) ;
307
* Stop logging. svc_activate starts logging and will leak a file
308
* descriptor and memory if this is not called prior.
310
static void stop_log( struct service *sp,
311
struct service_config *old_conf )
313
struct log *lp = SC_LOG( old_conf ) ;
315
if ( LOG_GET_TYPE( lp ) != L_NONE && SVC_IS_LOGGING( sp ) )
316
log_end( lp, SVC_LOG( sp ) ) ;
317
SVC_LOG( sp ) = NULL ;
321
* Stop any logging and restart if necessary.
322
* Note that this has the side-effect of using the new common log
323
* handle as it should.
325
static status_e restart_log( struct service *sp,
326
struct service_config *old_conf )
328
stop_log( sp, old_conf );
329
return( log_start( sp, &SVC_LOG( sp ) ) ) ;
334
* Unregister past versions, register new ones
335
* We do it the dumb way: first unregister; then register
336
* We try to be a little smart by checking if there has
337
* been any change in version numbers (if not, we do nothing).
338
* Also, we save the port number
340
static status_e readjust_rpc_service( struct service_config *old_scp,
341
struct service_config *new_scp )
344
uint16_t port = SC_PORT( old_scp ) ;
345
struct rpc_data *new_rdp = SC_RPCDATA( new_scp ) ;
346
struct rpc_data *old_rdp = SC_RPCDATA( old_scp ) ;
347
unsigned registered_versions = 0 ;
348
const char *func = "readjust_rpc_service" ;
351
SC_PORT( new_scp ) = SC_PORT( old_scp ) ;
353
if ( RD_MINVERS( old_rdp ) == RD_MINVERS( new_rdp ) &&
354
RD_MAXVERS( old_rdp ) == RD_MAXVERS( new_rdp ) )
357
for ( vers = RD_MINVERS( old_rdp ) ; vers <= RD_MAXVERS( old_rdp ) ; vers++ )
358
(void) pmap_unset( RD_PROGNUM( old_rdp ), vers ) ;
360
for ( vers = RD_MINVERS( new_rdp ) ; vers <= RD_MAXVERS( new_rdp ) ; vers++ )
361
if ( pmap_set( RD_PROGNUM( new_rdp ),
362
vers, SC_PROTOVAL( new_scp ), port ) )
363
registered_versions++ ;
366
"pmap_set failed. service=%s, program=%ld, version = %ld",
367
SC_ID( new_scp ), RD_PROGNUM( new_rdp ), vers ) ;
369
if ( registered_versions == 0 )
372
"No versions registered for RPC service %s", SC_ID( new_scp ) ) ;
374
* Avoid the pmap_unset
376
RD_MINVERS( new_rdp ) = RD_MAXVERS( new_rdp ) + 1 ;
379
#endif /* ! NO_RPC */
385
* Readjust service attributes.
387
* We assume that the following attributes are the same:
393
* Readjustment happens in 3 steps:
394
* 1) We swap the svc_conf fields
395
* This has the side-effect of free'ing the memory associated
396
* with the old service configuration when the new configuration
398
* 2) We readjust the fields that require some action to be taken:
401
* 3) We update the address control fields.
403
static status_e readjust( struct service *sp,
404
struct service_config **new_conf_ptr )
406
struct service_config *temp_conf ;
407
struct service_config *old_conf = SVC_CONF( sp ) ;
408
struct service_config *new_conf = *new_conf_ptr ;
409
char *sid = SVC_ID( sp ) ;
410
const char *func = "readjust" ;
412
msg( LOG_NOTICE, func, "readjusting service %s", sid ) ;
414
SWAP( SVC_CONF( sp ), *new_conf_ptr, temp_conf ) ;
416
if ( SC_IS_RPC( old_conf ) &&
417
readjust_rpc_service( old_conf, new_conf ) == FAILED )
421
* This is what happens if the INTERCEPT flag is toggled and an
422
* interceptor is running:
425
* Wait until the server dies (soft reconfig) or
426
* terminate the server (hard reconfig)
429
* Send a signal to the interceptor to tell it to stop intercepting
431
if ( SC_IS_INTERCEPTED( old_conf ) != SC_IS_INTERCEPTED( new_conf ) )
433
if ( SC_IS_INTERCEPTED( new_conf ) ) /* case 1 */
434
terminate_servers( sp ) ;
437
stop_interception( sp ) ;
438
msg( LOG_NOTICE, func, "Stopping interception for %s", sid ) ;
443
* See if the bind address was specified in both the old and new config,
444
* then if it changed, readjust the service. The algorithm is check to
445
* see if they are in the same address family, if so start a simple
446
* comparison based on the address family. If IPv4, the addresses can be
447
* compared directly, otherwise use the IPv6 macro. If they are not the
448
* same, terminate & restart the service.
450
if( (SC_BIND_ADDR(old_conf) != NULL) && (SC_BIND_ADDR(new_conf) != NULL) ) {
453
if ( SA(SC_BIND_ADDR(old_conf))->sa_family ==
454
SA(SC_BIND_ADDR(new_conf))->sa_family ) {
455
if ( SA(SC_BIND_ADDR(old_conf))->sa_family == AF_INET ) {
456
if ( SAIN(SC_BIND_ADDR(old_conf))->sin_addr.s_addr ==
457
SAIN(SC_BIND_ADDR(new_conf))->sin_addr.s_addr)
460
else if ( IN6_ARE_ADDR_EQUAL(
461
&SAIN6(SC_BIND_ADDR(old_conf))->sin6_addr,
462
&SAIN6(SC_BIND_ADDR(new_conf))->sin6_addr) )
467
terminate_servers( sp );
468
svc_deactivate( sp );
469
stop_log( sp, old_conf ); /* svc_activate re-starts logging */
475
/* If the service didn't have a bind address before, but does now,
476
* make sure the new bind directive takes effect.
478
if( (SC_BIND_ADDR(old_conf) == NULL) && (SC_BIND_ADDR(new_conf) != NULL) ) {
479
terminate_servers( sp );
481
stop_log( sp, old_conf ); /* svc_activate re-starts logging */
486
if( (SC_IPV4(old_conf) && SC_IPV6(new_conf)) ||
487
(SC_IPV6(old_conf) && SC_IPV4(new_conf)) ) {
488
terminate_servers( sp );
490
stop_log( sp, old_conf ); /* svc_activate re-starts logging */
495
return( restart_log( sp, old_conf ) ) ;