Exemple #1
0
static status_e set_fd_modes( struct service *sp )
{
   int sd = SVC_FD( sp ) ;
   const char *func = "set_fd_modes" ;

   /*
    * There is a possibility of blocking on a send/write if
    *
    * the service does not require forking (==> is internal) AND
    * it does not accept connections
    *
    * To avoid this, we put the descriptor in FNDELAY mode.
    * (if the service accepts connections, we still need to put the
    * 'accepted' connection in FNDELAY mode but this is done elsewhere)
    */
   if ( ! SVC_FORKS( sp ) && ! SVC_ACCEPTS_CONNECTIONS( sp ) &&
                              fcntl( sd, F_SETFL, FNDELAY ) == -1 )
   {
      msg( LOG_ERR, func,
         "fcntl failed (%m) for FNDELAY. service = %s", SVC_ID( sp ) ) ;
      return( FAILED ) ;
   }

   /*
    * Always set the close-on-exec flag
    */
   if ( fcntl( sd, F_SETFD, FD_CLOEXEC ) == -1 )
   {
      msg( LOG_ERR, func,
         "fcntl failed (%m) for close-on-exec. service = %s", SVC_ID( sp ) ) ;
      return( FAILED ) ;
   }
   return( OK ) ;
}
Exemple #2
0
/*
 * Resume a suspended service.
 */
void svc_resume( struct service *sp )
{
   const char *func = "svc_resume" ;

   FD_SET( SVC_FD( sp ), &ps.rws.socket_mask ) ;
   ps.rws.active_services++ ;
   if ( debug.on )
      msg( LOG_DEBUG, func, "Resumed service %s", SVC_ID( sp ) ) ;
   RESUME( sp ) ;
}
Exemple #3
0
void svc_dump( const struct service *sp, int fd )
{
   tabprint( fd, 0, "Service = %s\n", SC_NAME( SVC_CONF( sp ) ) ) ;
   tabprint( fd, 1, "State = %s\n",
                        nv_get_name( service_states, (int) SVC_STATE(sp) ) ) ;

   sc_dump( SVC_CONF( sp ), fd, 1, FALSE ) ;

   if ( SVC_IS_ACTIVE(sp) )
   {
      tabprint( fd, 1, "running servers = %d\n", SVC_RUNNING_SERVERS(sp) ) ;
      tabprint( fd, 1, "retry servers = %d\n", SVC_RETRIES(sp) ) ;
      tabprint( fd, 1, "attempts = %d\n", SVC_ATTEMPTS(sp) ) ;
      tabprint( fd, 1, "service fd = %d\n", SVC_FD(sp) ) ;
   }
   Sputchar( fd, '\n' ) ;
}
Exemple #4
0
/*
 * Suspend a service
 */
void svc_suspend( struct service *sp )
{
   const char *func = "svc_suspend" ;

   if ( ! SVC_IS_ACTIVE( sp ) )
   {
      msg( LOG_ERR, func, "service %s is not active", SVC_ID( sp ) ) ;
      return ;
   }

   FD_CLR( SVC_FD( sp ), &ps.rws.socket_mask ) ;
   ps.rws.active_services-- ;
   if ( debug.on )
      msg( LOG_DEBUG, func, "Suspended service %s", SVC_ID( sp ) ) ;
   
   SUSPEND( sp ) ;
}
Exemple #5
0
/*
 * This function closes all service descriptors. This should be called 
 * for all child processes that fork, but do not exec. This includes
 * redirect, builtins, and tcpmux. The close on exec flag takes care of
 * child processes that call exec. Without calling this, the listening 
 * fd's are not closed and reconfig will fail.
 */
void close_all_svc_descriptors(void)
{
   psi_h                     iter ;
   struct service            *osp ;

   /* Have to close all other descriptors here */
   iter = psi_create( SERVICES( ps ) ) ;
   if ( iter == NULL )
   {
        out_of_memory( "close_all_svc_descriptors" ) ;
        exit( 1 );
   }

   for ( osp = SP( psi_start( iter ) ) ; osp ; osp = SP( psi_next( iter ) ) )
        (void) Sclose( SVC_FD( osp ) ) ;
  
   psi_destroy( iter ) ;
}
Exemple #6
0
/*
 * Close the service descriptor.
 * If this is an RPC service, deregister it.
 * Close the log.
 */
void svc_deactivate( struct service *sp )
{
   if ( ! SVC_IS_AVAILABLE( sp ) )
      return ;

   deactivate( sp ) ;
   ps.rws.descriptors_free++ ;

   if ( SVC_IS_ACTIVE( sp ) )
   {
      FD_CLR( SVC_FD( sp ), &ps.rws.socket_mask ) ;
      ps.rws.active_services-- ;
   }

   ps.rws.available_services-- ;

   DISABLE( sp ) ;
}
Exemple #7
0
/*
 * If the service is single-threaded:
 *         if the descriptor is set in the socket mask, there must
 *         be a server running (or to be retried)
 *   If the service is multi-threaded:
 *         the descriptor must be always set
 */
static unsigned thread_check( struct service *sp, 
                               unsigned running_servers, 
                               unsigned retry_servers )
{
   unsigned error_count = 0 ;
   int sd = SVC_FD( sp ) ;
   char *sid = SVC_ID( sp ) ;
   const char *func = "thread_check" ;

   if ( SVC_WAITS( sp ) )
   {
      bool_int has_servers = ( running_servers + retry_servers != 0 ) ;

      if ( has_servers && FD_ISSET( sd, &ps.rws.socket_mask ) )
      {
         msg( LOG_ERR, func,
"Active single-threaded service %s: server running, descriptor set", sid ) ;
         error_count++ ;
      }
      if ( !has_servers && !FD_ISSET( sd, &ps.rws.socket_mask ) )
      {
         msg( LOG_ERR, func,
"Active single-threaded service %s: no server running, descriptor not set",
            sid ) ;
         error_count++ ;
      }
   }
   else
      if ( ! FD_ISSET( sd, &ps.rws.socket_mask ) )
      {
         msg( LOG_ERR, func,
            "Active multi-threaded service %s: descriptor not set", sid ) ;
         error_count++ ;
      }

   if ( error_count && debug.on )
      msg( LOG_DEBUG, func, "%s: %d errors detected", sid, error_count ) ;

   return( error_count ) ;
}
Exemple #8
0
static void deactivate( const struct service *sp )
{
   (void) Sclose( SVC_FD( sp ) ) ;

#ifdef HAVE_MDNS
   xinetd_mdns_deregister(SVC_CONF(sp));
#endif

   if (debug.on)
      msg(LOG_DEBUG, "deactivate", "%d Service %s deactivated", 
          getpid(), SC_NAME( SVC_CONF(sp) ) );

#ifndef NO_RPC
   if ( SC_IS_RPC( SVC_CONF( sp ) ) )
   {
      unsigned long vers ;
      const struct rpc_data *rdp = SC_RPCDATA( SVC_CONF( sp ) ) ;

      for ( vers = RD_MINVERS( rdp ) ; vers <= RD_MAXVERS( rdp ) ; vers++ ) {
         (void) pmap_unset( RD_PROGNUM( rdp ), vers ) ;
      }
   }
#endif   /* ! NO_RPC */
}
Exemple #9
0
static void consistency_check( enum check_type type )
{
   int         fd ;
   fd_set      socket_mask_copy ;
   unsigned    u ;
   int         errors ;
   unsigned    total_running_servers        = 0 ;
   unsigned    total_retry_servers          = 0 ;
   unsigned    error_count                  = 0 ;
   bool_int    service_count_check_failed   = FALSE ;
   const char  *func                        = "consistency_check" ;

   socket_mask_copy = ps.rws.socket_mask ;

   for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
   {
      register struct service *sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
      char *sid = SVC_ID( sp ) ;
      unsigned   running_servers ;
      unsigned   retry_servers ;

      error_count += refcount_check( sp, &running_servers, &retry_servers ) ;

      if ( SVC_IS_AVAILABLE( sp ) || SVC_IS_DISABLED ( sp ) )
      {
         /*
          * In this case, there may be some servers running
          */
         if ( FD_ISSET( SVC_FD( sp ), &socket_mask_copy ) )
         {
            if ( SVC_IS_DISABLED( sp ) )
            {
               msg( LOG_ERR, func,
                  "fd of disabled service %s still in socket mask", sid ) ;
               error_count++ ;
            }
            FD_CLR( SVC_FD( sp ), &socket_mask_copy ) ;
         }
         error_count += thread_check( sp, running_servers, retry_servers ) ;

         errors = service_count_check( sp, running_servers, retry_servers ) ;
         if ( ! errors && ! service_count_check_failed )
         {
            total_retry_servers += retry_servers ;
            total_running_servers += running_servers ;
         }
         if ( errors )
         {
            service_count_check_failed = TRUE ;
            error_count += errors ;
         }

         if ( SVC_IS_DISABLED( sp ) && SVC_RUNNING_SERVERS( sp ) == 0 )
         {
            msg( LOG_ERR, func,
               "disabled service %s has 0 running servers\n", sid ) ;
            error_count++ ;
            continue ;
         }
      }
      else
      {
         msg( LOG_ERR, func, "service %s not started", SVC_ID( sp ) ) ;
         error_count++ ;
      }
   }

   if ( ! service_count_check_failed )
   {
      if ( total_running_servers != pset_count( SERVERS( ps ) ) )
      {
         msg( LOG_ERR, func,
            "total running servers (%d) != number of running servers (%d)",
               total_running_servers, pset_count( SERVERS( ps ) ) ) ;
         error_count++ ;
      }
      if ( total_retry_servers != pset_count( RETRIES( ps ) ) )
      {
         msg( LOG_ERR, func,
            "total retry servers (%d) != number of retry servers (%d)",
               total_retry_servers, pset_count( RETRIES( ps ) ) ) ;
         error_count++ ;
      }
   }

   /*
    * Check if there are any descriptors set in socket_mask_copy
    */
   for ( fd = 0 ; fd < ps.ros.max_descriptors ; fd++ )
      if ( FD_ISSET( fd, &socket_mask_copy ) && ((fd != signals_pending[0]) && fd != signals_pending[1]))
      {
         msg( LOG_ERR, func,
            "descriptor %d set in socket mask but there is no service for it",
               fd ) ;
         error_count++ ;
      }

   if ( error_count != 0 )
      msg( LOG_WARNING, func,
            "Consistency check detected %d errors", error_count ) ;
   else
      if ( type == USER_REQUESTED || debug.on )
         msg( LOG_INFO, func, "Consistency check passed" ) ;

   if( type == PERIODIC ) 
      if ( xtimer_add( periodic_check, ps.ros.cc_interval ) == -1 )
         msg( LOG_ERR, func, "Failed to start consistency timer" ) ;
}
Exemple #10
0
/*
 * Get a new connection request and initialize 'cp' appropriately
 */
static status_e get_connection( struct service *sp, connection_s *cp )
{
   struct service_config *scp = SVC_CONF( sp );
   socklen_t sin_len;
   const char *func = "get_connection" ;
   int on = 1;

   if( SC_IPV4(scp) ) sin_len = sizeof(struct sockaddr_in);
   if( SC_IPV6(scp) ) sin_len = sizeof(struct sockaddr_in6);

   if ( SVC_SOCKET_TYPE( sp ) == SOCK_STREAM ) {
      /* If it's a TCP socket, and we're set to wait, the accept is
       * done by the child process.  Don't set NEW_DESCRIPTOR, since
       * there isn't one.  The descriptor will be/was removed from
       * the descriptor set in svc_suspend and re-enabled in svc_resume.
       */
      if( SC_WAITS( scp ) ) {
         cp->co_descriptor = SVC_FD( sp );
      } else {
         cp->co_descriptor = accept( SVC_FD( sp ), &(cp->co_remote_address.sa),
                                     &sin_len ) ;
	 if (cp->co_descriptor != -1)
             M_SET( cp->co_flags, COF_NEW_DESCRIPTOR ) ;
      }

      if ( cp->co_descriptor == -1 )
      {
	 if ((errno == EMFILE) || (errno == ENFILE))
	     cps_service_stop(sp, "no available descriptors");
	 else
             msg( LOG_ERR, func, "service %s, accept: %m", SVC_ID( sp ) ) ;
         return( FAILED ) ;
      }

      if( SC_NODELAY( scp ) && (SC_PROTOVAL( scp ) == IPPROTO_TCP) )
         if( setsockopt(SVC_FD(sp), IPPROTO_TCP, TCP_NODELAY, 
                        (char *)&on, sizeof( on ) ) < 0 )
            msg( LOG_WARNING, func, "service %s, setsockopt: %m", SVC_ID(sp));

      if( SC_KEEPALIVE( scp ) && (SC_PROTOVAL( scp ) == IPPROTO_TCP) )
      {
         if( setsockopt(SVC_FD(sp), SOL_SOCKET, SO_KEEPALIVE, 
                        (char *)&on, sizeof( on ) ) < 0 )
            msg( LOG_WARNING, func, "service %s, setsockopt: %m", SVC_ID(sp));
      }
      
      if( SC_IPV6(scp) && !(SC_V6ONLY( scp ))  && 
         (IN6_IS_ADDR_V4MAPPED(&cp->co_remote_address.sa_in6.sin6_addr) || 
	  IN6_IS_ADDR_V4COMPAT(&cp->co_remote_address.sa_in6.sin6_addr)) ) 
      {
         int af = AF_INET;
         if( setsockopt(cp->co_descriptor, IPPROTO_IPV6,
               IPV6_ADDRFORM, &af, sizeof( af ) ) ) {
            if( debug.on ) msg( LOG_WARNING, func, "service %s, IPV6_ADDRFORM setsockopt() failed: %m", SVC_ID( sp) );
         }
      }

      M_SET( cp->co_flags, COF_HAVE_ADDRESS ) ;
   }
   else
   {
      if ( SVC_SOCKET_TYPE( sp ) == SOCK_DGRAM )
      {
         char t_ch ;
	 ssize_t val;

         /*
          * This trick is done to get the remote address.
          * select(2) guaranteed that we won't block on the recvfrom
          */
	 val = recvfrom( SVC_FD( sp ), &t_ch, 1, MSG_PEEK,
                              &cp->co_remote_address.sa, &sin_len );
         if ( val == (ssize_t)-1 )
         {
            msg( LOG_ERR, func, "service %s, recvfrom: %m", SVC_ID( sp ) ) ;
            return( FAILED ) ;
         }
         M_SET( cp->co_flags, COF_HAVE_ADDRESS ) ;
      }

      cp->co_descriptor = SVC_FD( sp ) ;
   }

   return( OK ) ;
}
Exemple #11
0
/*
 * Activate a service. 
 */
status_e svc_activate( struct service *sp )
{
   struct service_config    *scp = SVC_CONF( sp ) ;
   status_e                  status ;
   const char                     *func = "svc_activate" ;

   /*  No activation for MUXCLIENTS.
    */

   if (SC_IS_MUXCLIENT( scp ))
   {
      return( OK );
   }

   if( SC_IPV4( scp ) ) {
      SVC_FD(sp) = socket( AF_INET, 
                           SC_SOCKET_TYPE( scp ), SC_PROTOVAL( scp ) ) ;
   } else if( SC_IPV6( scp ) ) {
      SVC_FD(sp) = socket( AF_INET6, 
                           SC_SOCKET_TYPE( scp ), SC_PROTOVAL( scp ) ) ;
   }

   if ( SVC_FD(sp) == -1 )
   {
      msg( LOG_ERR, func,
                  "socket creation failed (%m). service = %s", SC_ID( scp ) ) ;
      return( FAILED ) ;
   }

   if ( set_fd_modes( sp ) == FAILED )
   {
      (void) Sclose( SVC_FD(sp) ) ;
      return( FAILED ) ;
   }

#ifndef NO_RPC
   if ( SC_IS_RPC( scp ) )
      status = activate_rpc( sp ) ;
   else
#endif   /* ! NO_RPC */
      status = activate_normal( sp ) ;
   
   if ( status == FAILED )
   {
      (void) Sclose( SVC_FD(sp) ) ;
      return( FAILED ) ;
   }

#ifdef HAVE_MDNS
   xinetd_mdns_register(scp);
#endif

   if ( log_start( sp, &SVC_LOG(sp) ) == FAILED )
   {
      deactivate( sp ) ;
      return( FAILED ) ;
   }

   /*
    * Initialize the service data
    */
   SVC_RUNNING_SERVERS(sp)   = SVC_RETRIES(sp) = 0 ;

   if ( SC_MUST_LISTEN( scp ) )
      (void) listen( SVC_FD(sp), LISTEN_BACKLOG ) ;

   ps.rws.descriptors_free-- ;

   SVC_STATE(sp) = SVC_ACTIVE ;

   FD_SET( SVC_FD(sp), &ps.rws.socket_mask ) ;
   if ( SVC_FD(sp) > ps.rws.mask_max )
      ps.rws.mask_max = SVC_FD(sp) ;

   ps.rws.active_services++ ;
   ps.rws.available_services++ ;

   return( OK ) ;
}
Exemple #12
0
static status_e activate_normal( struct service *sp )
{
   union xsockaddr         tsin;
   int                     sd             = SVC_FD( sp ) ;
   struct service_config  *scp            = SVC_CONF( sp ) ;
   uint16_t                service_port   = SC_PORT( scp ) ;
   char                   *sid            = SC_ID( scp ) ;
   const char             *func           = "activate_normal" ;
   unsigned int            sin_len        = sizeof(tsin);
   int                     on             = 1;
#ifdef IPV6_V6ONLY
   int                     v6on           = 0;
#endif

   if( SC_BIND_ADDR(scp) != NULL )
      memcpy(&tsin, SC_BIND_ADDR(scp), sin_len);
   else
      memset(&tsin, 0, sin_len);
   
   if( SC_IPV4( scp ) ) {
      tsin.sa_in.sin_family = AF_INET ;
      tsin.sa_in.sin_port = htons( service_port ) ;
      sin_len = sizeof(struct sockaddr_in);
   } else if( SC_IPV6( scp ) ) {
      tsin.sa_in6.sin6_family = AF_INET6;
      tsin.sa_in6.sin6_port = htons( service_port );
      sin_len = sizeof(struct sockaddr_in6);
   }

#ifdef IPV6_V6ONLY
   if( SC_IPV6(scp) ) {
      if( SC_SPECIFIED(scp, A_V6ONLY) ) {
         v6on = 1;
      } else {
         v6on = 0;
      }
      if( setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&v6on, sizeof(v6on)) < 0 ) {
         msg( LOG_ERR, func, "Setting IPV6_V6ONLY option failed (%m)" );
      }
   }
#endif

   if ( setsockopt( sd, SOL_SOCKET, SO_REUSEADDR, 
                    (char *) &on, sizeof( on ) ) == -1 )
      msg( LOG_WARNING, func, 
           "setsockopt SO_REUSEADDR failed (%m). service = %s", sid ) ;

   if( SC_NODELAY( scp ) && (SC_PROTOVAL(scp) == IPPROTO_TCP) )
   {
      if ( setsockopt( sd, IPPROTO_TCP, TCP_NODELAY, 
                       (char *) &on, sizeof( on ) ) == -1 )
         msg( LOG_WARNING, func, 
              "setsockopt TCP_NODELAY failed (%m). service = %s", sid ) ;
   }

   if( SC_KEEPALIVE( scp ) && (SC_PROTOVAL(scp) == IPPROTO_TCP) ) 
   {
      if( setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, 
                     (char *)&on, sizeof( on ) ) < 0 )
         msg( LOG_WARNING, func, 
              "setsockopt SO_KEEPALIVE failed (%m). service = %s", sid ) ;
   }

   if ( bind( sd, &tsin.sa, sin_len ) == -1 )
   {
      msg( LOG_ERR, func, "bind failed (%m). service = %s", sid ) ;
      return( FAILED ) ;
   }

#ifdef IN_MULTICAST
   if( SC_IPV4(scp) && IN_MULTICAST( ntohl(tsin.sa_in.sin_addr.s_addr) ) ) {
      struct ifaddrs *addrs, *addr;
      struct ip_mreq mreq;
      
      if (getifaddrs(&addrs) == 0) {
         addr = addrs;

         while (addr)
         {
            if (addr->ifa_addr && (addr->ifa_flags & IFF_MULTICAST))
            {
               mreq.imr_multiaddr.s_addr = tsin.sa_in.sin_addr.s_addr;
               mreq.imr_interface.s_addr = ((struct sockaddr_in *)addr->ifa_addr)->sin_addr.s_addr;
               setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
            }
            addr = addr->ifa_next;
         }
         freeifaddrs(addrs);
         if ( debug.on )
               msg( LOG_DEBUG, func, "Adding multicast membership." );
      }
      else {
         msg( LOG_ERR, func, "getifaddrs failed (%m). service = %s", sid );
      }
   }
#endif

   return( OK ) ;
}
Exemple #13
0
static status_e activate_rpc( struct service *sp )
{
   union xsockaddr        tsin;
   socklen_t              sin_len = sizeof(tsin);
   unsigned long          vers ;
   struct service_config *scp = SVC_CONF( sp ) ;
   struct rpc_data       *rdp = SC_RPCDATA( scp ) ;
   char                  *sid = SC_ID( scp ) ;
   unsigned               registered_versions = 0 ;
   int                    sd = SVC_FD( sp ) ;
   const char            *func = "activate_rpc" ;

   if( SC_BIND_ADDR(scp) != 0 )
      memcpy( &tsin, SC_BIND_ADDR(scp), sizeof(tsin) );
   else
      memset( &tsin, 0, sizeof(tsin));

   if ( SC_PROTOVAL ( scp ) == IPPROTO_TCP ) {
      M_SET ( scp->sc_xflags, SF_NOLIBWRAP );
   }
   if( SC_IPV4( scp ) ) {
      tsin.sa_in.sin_family = AF_INET ;
      sin_len = sizeof(struct sockaddr_in);
   } else if( SC_IPV6( scp ) ) {
      tsin.sa_in6.sin6_family = AF_INET6 ;
      sin_len = sizeof(struct sockaddr_in6);
   }

   if ( bind( sd, &tsin.sa, sin_len ) == -1 )
   {
      msg( LOG_ERR, func, "bind failed (%m). service = %s", sid ) ;
      return( FAILED ) ;
   }

   /*
    * Find the port number that was assigned to the socket
    */
   if ( getsockname( sd, &tsin.sa, &sin_len ) == -1 )
   {
      msg( LOG_ERR, func,
            "getsockname failed (%m). service = %s", sid ) ;
      return( FAILED ) ;
   }
   
   if( tsin.sa.sa_family == AF_INET )
      SC_SET_PORT( scp, ntohs( tsin.sa_in.sin_port ) ) ;
   else if( tsin.sa.sa_family == AF_INET6 )
      SC_SET_PORT( scp, ntohs( tsin.sa_in6.sin6_port ) ) ;

   /*
    * Try to register as many versions as possible
    */
   for ( vers = RD_MINVERS( rdp ) ; vers <= RD_MAXVERS( rdp ) ; vers++ ) {
/*      Is this right?  For instance, if we have both tcp and udp services,
 *      this will unregister the previously registered protocol.
 *      pmap_unset(RD_PROGNUM(rdp), vers);
 */
      if ( pmap_set( RD_PROGNUM( rdp ), vers, SC_PROTOVAL( scp ), 
			      SC_PORT( scp ) ) )
         registered_versions++ ;
      else
         msg( LOG_ERR, func,
            "pmap_set failed. service=%s program=%ld version=%ld",
               sid, RD_PROGNUM( rdp ), vers ) ;
      sleep(1);
   }

   if ( debug.on )
      msg( LOG_DEBUG, func,
            "Registered %d versions of %s", registered_versions, sid ) ;

   return( ( registered_versions == 0 ) ? FAILED : OK ) ;
}