fixes init script for non ipv6 enabled systems #472755
[packages/xinetd.git] / xinetd / reconfig.c
1 /*
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.
6  */
7
8
9 #include "config.h"
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <syslog.h>
13 #include <signal.h>
14 #include <memory.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <netinet/in.h>
18 #ifndef NO_RPC
19  #ifdef HAVE_RPC_PMAP_CLNT_H
20   #ifdef __sun
21    #include <rpc/types.h>
22    #include <rpc/auth.h>
23   #endif
24   #include <rpc/types.h>
25   #include <rpc/xdr.h>
26   #include <rpc/auth.h>
27   #include <rpc/clnt.h>
28   #include <rpc/pmap_clnt.h>
29  #endif
30  #include <rpc/rpc.h>
31 #endif
32
33 #include "reconfig.h"
34 #include "msg.h"
35 #include "sconf.h"
36 #include "conf.h"
37 #include "confparse.h"
38 #include "state.h"
39 #include "main.h"
40 #include "retry.h"
41 #include "logctl.h"
42 #include "options.h"
43
44
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);
49
50 #define SWAP( x, y, temp )         (temp) = (x), (x) = (y), (y) = (temp)
51
52
53 /*
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
57  * errors).
58  */
59 void hard_reconfig( void )
60 {
61    struct service            *osp ;
62    struct service_config     *nscp ;
63    struct configuration      new_conf ;
64    psi_h                     iter ;
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" ;
70
71
72    msg( LOG_NOTICE, func, "Starting reconfiguration" ) ;
73
74    if ( cnf_get( &new_conf ) == FAILED )
75    {
76       msg( LOG_WARNING, func, "reconfiguration failed" ) ;
77       return ;
78    }
79
80    iter = psi_create( SERVICES( ps ) ) ;
81    if ( iter == NULL )
82    {
83       out_of_memory( func ) ;
84       cnf_free( &new_conf ) ;
85       return ;
86    }
87
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 ) ;
91
92    /*
93     * Glossary:
94     *      Sconf: service configuration
95     *      Lconf: list of service configurations
96     *
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.
101     */
102    for ( osp = SP( psi_start( iter ) ) ; osp ; osp = SP( psi_next( iter ) ) )
103    {
104       char *sid = SVC_ID( osp ) ;
105       boolean_e drop_service ;
106
107       /*
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.
111        */
112       if (  (nscp = cnf_extract( &new_conf, SVC_CONF( osp ) )) )
113       {
114          /*
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
118           * configuration).
119           */
120          if ( readjust( osp, &nscp ) == OK )
121          {
122             old_services++ ;
123             drop_service = NO ;
124          }
125          else   /* the readjustment failed */
126             drop_service = YES ;
127          sc_free( nscp ) ;
128       }
129       else
130          drop_service = YES ;
131
132       if ( drop_service == YES )
133       {
134          /*
135           * Procedure for disabling a service:
136           *
137           *      a. Deactivate the service to prevent new connections
138           *      b. Terminate running servers and cancel retry attempts, in case
139           *         of reconfiguration
140           */
141          svc_deactivate( osp ) ;
142          terminate_servers( osp ) ;
143          cancel_service_retries( osp ) ;
144
145          /*
146           * Deactivate the service; the service will be deleted only
147           * if its reference count drops to 0.
148           */
149          /* Always remove the service, even if not all the children
150           * have been killed, or there are other references.
151           */
152          psi_remove( iter ) ;
153          msg( LOG_NOTICE, func, "service %s deactivated", sid ) ;
154          if ( SVC_RELE( osp ) == 0 ) {
155             svc_release( osp );
156          } else
157             msg( LOG_ERR, func, "Errors deactivating service %s", sid ) ;
158          dropped_services++ ;
159       }
160    }
161
162    psi_destroy( iter ) ;
163
164    /*
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.
167     */
168    close_default_log( &new_conf, def_log ) ;
169
170    /*
171     * At this point the new Lconf only contains services that were not
172     * in the old Lconf.
173     */
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 ) ;
178
179    if ( stayalive_option == 0 ) {
180       if ( ps.rws.available_services == 0 )
181       {
182          msg( LOG_CRIT, func, "No available services. Exiting" );
183          if ( ps.ros.pid_file ) {
184             unlink(ps.ros.pid_file);
185          }
186          exit( 1 ) ;
187       }
188    }
189
190    cnf_free( &new_conf ) ; 
191 }
192
193
194 static void swap_defaults( struct configuration *new_conf )
195 {
196    struct service_config *temp ;
197
198    DEFAULT_LOG_ERROR( ps ) = FALSE ;
199    DEFAULT_LOG( ps ) = NULL ;
200    SWAP( DEFAULTS( ps ), CNF_DEFAULTS( new_conf ), temp ) ;
201 }
202
203
204 static void close_default_log(struct configuration *confp, xlog_h def_log)
205 {
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) ;
209 }
210
211
212 static void sendsig( struct server *serp, int sig )
213 {
214    char      *sid   = SVC_ID( SERVER_SERVICE( serp ) ) ;
215    pid_t      pid   = SERVER_PID( serp ) ;
216    const char *func = "sendsig" ;
217
218    /*
219     * Always use a positive pid, because of the semantics of kill(2)
220     */
221    if ( pid > 0 )
222    {
223       msg( LOG_WARNING, func, "Sending signal %d to %s server %d",
224                                     sig, sid, pid ) ;
225       kill( pid, sig ) ;
226       if ((sig == SIGTERM) || (sig == SIGKILL))
227       {
228          int i, killed = 0;
229          struct timeval tv;
230
231          /*
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
234           * its demise.
235           */
236
237          tv.tv_sec = 0;
238          tv.tv_usec = 500000; /* half a second */
239          for (i=0; i<8; i++)
240          {
241             if( server_lookup(pid) == NULL )
242             {
243                killed = 1;
244                break;
245             } else {
246                int wret = waitpid(pid, NULL, WNOHANG);
247                if (wret == pid) {
248                   killed = 1;
249                   break;
250                }
251                server_end(serp);
252             }
253          
254             /* May not have responded to TERM, send a KILL */
255             if ( i == 5)
256                kill( pid, SIGKILL ) ;
257                  
258             /* Not dead yet, give some time. */
259             select(0, NULL, NULL, NULL, &tv);
260          }
261
262          /*
263           * If it didn't die, expect problems rebinding to this port if
264           * a hard_reconfig is in process.
265           */
266          if (!killed)
267             msg( LOG_ERR, func, "Server %d did not exit after SIGKILL", 
268                   pid ) ;
269          /* no need to server_end() here.  The killed process will generate
270           * a sigchld, which will invoke the signal handler, and clean things
271           * up there.
272           */
273       }
274    } 
275    else if ( pid != 0 )
276       msg( LOG_ERR, func, "Negative server pid = %d. Service %s", pid, sid ) ;
277 }
278
279
280 /*
281  * Send signal sig to all running servers of service sp
282  */
283 static void deliver_signal( struct service *sp, int sig )
284 {
285    unsigned u ;
286
287    for ( u = 0 ; u < pset_count( SERVERS( ps ) ) ; u++ )
288    {
289       struct server *serp ;
290
291       serp = SERP( pset_pointer( SERVERS( ps ), u ) ) ;
292       if ( SERVER_SERVICE( serp ) == sp ) {
293          sendsig( serp, sig ) ;
294          if ( (sig == SIGTERM) || (sig == SIGKILL) )
295             u--;
296       }
297    }
298 }
299
300
301 /*
302  * Terminate all servers of the specified service
303  */
304 void terminate_servers( struct service *sp )
305 {
306    int sig = SC_IS_INTERNAL( SVC_CONF( sp ) ) ? SIGTERM : SIGKILL ;
307
308    deliver_signal( sp, sig ) ;
309 }
310
311
312 static void stop_interception( struct service *sp )
313 {
314    deliver_signal( sp, INTERCEPT_SIG ) ;
315 }
316
317 /*
318  * Stop logging. svc_activate starts logging and will leak a file
319  * descriptor and memory if this is not called prior.
320  */
321 static void stop_log( struct service *sp, 
322                               struct service_config *old_conf )
323 {
324    struct log *lp = SC_LOG( old_conf ) ;
325
326    if ( LOG_GET_TYPE( lp ) != L_NONE && SVC_IS_LOGGING( sp ) )
327       log_end( lp, SVC_LOG( sp ) ) ;
328    SVC_LOG( sp ) = NULL ;
329 }
330
331 /*
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.
335  */
336 static status_e restart_log( struct service *sp, 
337                               struct service_config *old_conf )
338 {
339    stop_log( sp, old_conf ); 
340    return( log_start( sp, &SVC_LOG( sp ) ) ) ;
341 }
342
343
344 /*
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
350  */
351 static status_e readjust_rpc_service( struct service_config *old_scp, 
352                                        struct service_config *new_scp )
353 {
354    unsigned long      vers ;
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" ;
360
361 #ifndef NO_RPC
362    SC_PORT( new_scp ) = SC_PORT( old_scp ) ;
363
364    if ( RD_MINVERS( old_rdp ) == RD_MINVERS( new_rdp ) &&
365             RD_MAXVERS( old_rdp ) == RD_MAXVERS( new_rdp ) )
366       return( OK ) ;
367
368    for ( vers = RD_MINVERS( old_rdp ) ; vers <= RD_MAXVERS( old_rdp ) ; vers++ )
369        (void) pmap_unset( RD_PROGNUM( old_rdp ), vers ) ;
370
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++ ;
375       else
376          msg( LOG_ERR, func, 
377             "pmap_set failed. service=%s, program=%ld, version = %ld",
378                SC_ID( new_scp ), RD_PROGNUM( new_rdp ), vers ) ;
379
380    if ( registered_versions == 0 )
381    {
382       msg( LOG_ERR, func,
383             "No versions registered for RPC service %s", SC_ID( new_scp ) ) ;
384       /*
385        * Avoid the pmap_unset
386        */
387       RD_MINVERS( new_rdp ) = RD_MAXVERS( new_rdp ) + 1 ;
388       return( FAILED ) ;
389    }
390 #endif   /* ! NO_RPC */
391    return( OK ) ;
392 }
393
394
395 /*
396  * Readjust service attributes. 
397  *
398  * We assume that the following attributes are the same:
399  *         wait
400  *         socket_type
401  *         type
402  *         protocol
403  *
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
408  *            is destroyed.
409  *      2) We readjust the fields that require some action to be taken:
410  *            RPC mapping
411  *            log file open
412  *      3) We update the address control fields.
413  */
414 static status_e readjust( struct service *sp, 
415                            struct service_config **new_conf_ptr )
416 {
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" ;
422
423    msg( LOG_NOTICE, func, "readjusting service %s", sid ) ;
424
425    SWAP( SVC_CONF( sp ), *new_conf_ptr, temp_conf ) ;
426
427    if ( SC_IS_RPC( old_conf ) &&
428                   readjust_rpc_service( old_conf, new_conf ) == FAILED )
429       return( FAILED ) ;
430    
431    /*
432     * This is what happens if the INTERCEPT flag is toggled and an
433     * interceptor is running:
434     *
435     * Case 1: clear->set
436     *      Wait until the server dies (soft reconfig) or
437     *      terminate the server (hard reconfig)
438     *
439     * Case 2: set->clear
440     *    Send a signal to the interceptor to tell it to stop intercepting
441     */
442    if ( SC_IS_INTERCEPTED( old_conf ) != SC_IS_INTERCEPTED( new_conf ) )
443    {
444       if ( SC_IS_INTERCEPTED( new_conf ) )         /* case 1 */
445          terminate_servers( sp ) ;
446       else                                       /* case 2 */
447       {
448          stop_interception( sp ) ;
449          msg( LOG_NOTICE, func, "Stopping interception for %s", sid ) ;
450       }
451    }
452
453    /* 
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. 
460     */
461    if( (SC_BIND_ADDR(old_conf) != NULL) && (SC_BIND_ADDR(new_conf) != NULL) ) {
462       int same = 0;
463
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)
469                same = 1;
470          }
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) )
474             same = 1;
475       }
476       
477       if ( !same ) {
478          terminate_servers( sp );
479          svc_deactivate( sp );
480          stop_log( sp, old_conf ); /* svc_activate re-starts logging */
481          svc_activate( sp );
482          return OK;
483       }
484    }
485
486    /* If the service didn't have a bind address before, but does now,
487     * make sure the new bind directive takes effect.
488     */
489    if( (SC_BIND_ADDR(old_conf) == NULL) && (SC_BIND_ADDR(new_conf) != NULL) ) {
490       terminate_servers( sp );
491       svc_deactivate(sp);
492       stop_log( sp, old_conf ); /* svc_activate re-starts logging */
493       svc_activate(sp);
494       return OK;
495    }
496
497    if( (SC_IPV4(old_conf) && SC_IPV6(new_conf)) || 
498          (SC_IPV6(old_conf) && SC_IPV4(new_conf)) ) {
499       terminate_servers( sp );
500       svc_deactivate(sp);
501       stop_log( sp, old_conf ); /* svc_activate re-starts logging */
502       svc_activate(sp);
503       return OK;
504    }
505
506    return( restart_log( sp, old_conf ) ) ;
507 }
508