Example #1
0
static void stream_chargen( const struct server *serp )
{
   char   line_buf[ LINE_LENGTH+2 ] ;
   int    descriptor = SERVER_FD( serp ) ;
   struct service *svc = SERVER_SERVICE( serp );

   if( SVC_WAITS( svc ) ) {
      descriptor = accept(descriptor, NULL, NULL);
      if ( descriptor == -1 ) {
         if ((errno == EMFILE) || (errno == ENFILE))
            cps_service_stop(svc, "no available descriptors");
         return;
      }
   }

   (void) shutdown( descriptor, 0 ) ;
   close_all_svc_descriptors();

   for ( ;; )
   {
      if ( generate_line( line_buf, sizeof( line_buf ) ) == NULL )
         break ;
      if ( write_buf( descriptor, line_buf, sizeof( line_buf ) ) == FAILED )
         break ;
   }
   if( SVC_WAITS( svc ) ) /* Service forks, so close it */
      Sclose(descriptor);
}
Example #2
0
static void stream_discard( const struct server *serp )
{
   char  buf[ BUFFER_SIZE ] ;
   int   cc ;
   int    descriptor = SERVER_FD( serp ) ;
   struct service *svc = SERVER_SERVICE( serp ) ;;

   if( SVC_WAITS( svc ) ) {
      descriptor = accept(descriptor, NULL, NULL);
      if ( descriptor == -1 ) {
         if ((errno == EMFILE) || (errno == ENFILE))
            cps_service_stop(svc, "no available descriptors");
         return;
      }
   }

   close_all_svc_descriptors();

   for ( ;; )
   {
      cc = read( descriptor, buf, sizeof( buf ) ) ;
      if ( (cc == 0) || ((cc == -1) && (errno != EINTR)) )
         break ;
   }
   if( SVC_WAITS( svc ) ) /* Service forks, so close it */
      Sclose(descriptor);
}
Example #3
0
/*
 * Get a connection for the specified service and return a pointer
 * to a new connection_s
 */
connection_s *conn_new( struct service *sp )
{
   connection_s    new_conn ;
   connection_s   *cp ;
   const char     *func = "conn_new" ;

   CLEAR( new_conn ) ;

   /*
    * The reason we first get the connection and then allocate a
    * 'connection_s' is because we want to always consume some input.
    */
   if ( get_connection( sp, &new_conn ) == FAILED )
      return( NULL ) ;

   new_conn.co_sp = sp ;
   SVC_HOLD( sp ) ;
   
   if ( SVC_WAITS( sp ) )
      svc_suspend( sp ) ;

   cp = NEW_CONN() ;
   if ( cp == CONN_NULL )
   {
      out_of_memory( func ) ;
      conn_free( &new_conn, 0 ) ;
      CLEAR( new_conn ) ;
      return( CONN_NULL ) ;
   }
   memcpy(cp, &new_conn, sizeof(connection_s));
   return( cp ) ;
}
Example #4
0
static void stream_echo( const struct server *serp )
{
   char   buf[ BUFFER_SIZE ] ;
   ssize_t    cc ;
   int    descriptor = SERVER_FD( serp ) ;
   struct service *svc = SERVER_SERVICE( serp ) ;;

   if( SVC_WAITS( svc ) ) {
      descriptor = accept(descriptor, NULL, NULL);
      if ( descriptor == -1 ) {
         if ((errno == EMFILE) || (errno == ENFILE))
            cps_service_stop(svc, "no available descriptors");
         return;
      }
   }

   close_all_svc_descriptors();

   for ( ;; )
   {
      cc = read( descriptor, buf, sizeof( buf ) ) ;
      if ( cc == 0 )
         break ;
      if ( cc == (ssize_t)-1 ) {
         if ( errno == EINTR )
            continue ;
         else
            break ;
      }

      if ( write_buf( descriptor, buf, cc ) == FAILED )
         break ;
   }
   if( SVC_WAITS( svc ) ) /* Service forks, so close it */
      Sclose(descriptor);
}
Example #5
0
/*
 * Invoked when a server of the specified service dies
 */
void svc_postmortem( struct service *sp, struct server *serp )
{
   struct service  *co_sp   = SERVER_CONNSERVICE( serp ) ;
   connection_s    *cp      = SERVER_CONNECTION( serp ) ;
   const char      *func    = "svc_postmortem" ;

   SVC_DEC_RUNNING_SERVERS( sp ) ;

   /*
    * Log information about the server that died
    */
   if ( SVC_IS_LOGGING( sp ) )
   {
      if ( SERVER_WRITES_TO_LOG(serp) )
      {
         if ( debug.on )
            msg( LOG_DEBUG, func,
                        "Checking log size of %s service", SVC_ID( sp ) ) ;
         xlog_control( SVC_LOG( sp ), XLOG_SIZECHECK ) ;
      }
      svc_log_exit( sp, serp ) ;
   }

   /*
    * Now check if we have to check the log size of the service that owns
    * the connection
    */
   if ( co_sp != sp && SVC_IS_LOGGING( co_sp ) )
      xlog_control( SVC_LOG( co_sp ), XLOG_SIZECHECK ) ;

   if (!SVC_WAITS(sp)) {
      conn_free( cp, 1 ) ;
      cp = NULL;
   } else {
      if (cp) {
         if ( SVC_SOCKET_TYPE( sp ) == SOCK_DGRAM )
            drain( cp->co_descriptor ) ;
         free(cp);
         cp = NULL;
         if( SVC_RELE( sp ) == 0 )
            svc_release( sp ); /* shouldn't be 0, but should remove from
                                * pset if it is... */
      }
      svc_resume(sp);
   }
}
Example #6
0
static void stream_daytime( const struct server *serp )
{
   char  time_buf[ BUFFER_SIZE ] ;
   unsigned int buflen = sizeof( time_buf ) ;
   int    descriptor = SERVER_FD( serp ) ;
   struct service *svc = SERVER_SERVICE( serp ) ;;

   if( SVC_WAITS( svc ) ) {
      descriptor = accept(descriptor, NULL, NULL);
      if ( descriptor == -1 ) {
         if ((errno == EMFILE) || (errno == ENFILE))
            cps_service_stop(svc, "no available descriptors");
         return;
      }
   }
   daytime_protocol( time_buf, &buflen ) ;
   (void) write_buf( descriptor, time_buf, buflen ) ;
   Sclose(descriptor);
}
Example #7
0
static void stream_time( const struct server *serp )
{
   unsigned char time_buf[4];
   int descriptor = SERVER_FD( serp );
   struct service *svc = SERVER_SERVICE( serp );

   if( SVC_WAITS( svc ) ) {
      descriptor = accept(descriptor, NULL, NULL);
      if ( descriptor == -1 ) {
         if ((errno == EMFILE) || (errno == ENFILE))
            cps_service_stop(svc, "no available descriptors");
         return;
      }
   }

   time_protocol( time_buf ) ;
   (void) write_buf( descriptor, (char *) time_buf, 4 ) ;

   Sclose(descriptor);
}
Example #8
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 ) ;
}
Example #9
0
static void tcpmux_handler( const struct server *serp )
{
   char      svc_name[ BUFFER_SIZE ] ;
   int       cc ;
   int       descriptor = SERVER_FD( serp ) ;
   const     struct service *svc = SERVER_SERVICE( serp ) ;
   unsigned  u;
   struct    service *sp = NULL;
   struct    server server, *nserp;
   struct    service_config *scp = NULL;

   close_all_svc_descriptors();

   /*  Read in the name of the service in the format "svc_name\r\n".
    *
    *  XXX: should loop on partial reads (could probably use Sread() if
    *  it wasn't thrown out of xinetd source code a few revisions back).
    */
   do
   {
      cc = read( descriptor, svc_name, sizeof( svc_name ) ) ;
   } while (cc == -1 && errno == EINTR);

   if ( cc <= 0 )
   {
      msg(LOG_ERR, "tcpmux_handler", "read failed");
      exit(0);
   }

   if ( ( cc <= 2 ) ||
        ( ( svc_name[cc - 1] != '\n' ) || ( svc_name[cc - 2] != '\r' ) ) )
   {
      if ( debug.on )
         msg(LOG_DEBUG, "tcpmux_handler", "Invalid service name format.");
      
      exit(0);
   }

   svc_name[cc - 2] = '\0';  /*  Remove \r\n for compare */

   if ( debug.on )
   {
      msg(LOG_DEBUG, "tcpmux_handler", "Input (%d bytes) %s as service name.",
          cc, svc_name);
   }

   /*  Search the services for the a match on name.
    */

   for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
   {
      sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;

      if ( strcasecmp( svc_name, SC_NAME( SVC_CONF( sp ) ) ) == 0 )
      {
         /*  Found the pointer. Validate its type.
          */
         scp = SVC_CONF( sp );
/*
         if ( ! SVC_IS_MUXCLIENT( sp ) )
         {
            if ( debug.on )
            {
               msg(LOG_DEBUG, "tcpmux_handler", "Non-tcpmux service name: %s.",
                   svc_name);
            }
            exit(0);
         }
*/

         /*  Send the accept string if we're a PLUS (+) client.
          */

         if ( SVC_IS_MUXPLUSCLIENT( sp ) )
         {
            if ( Swrite( descriptor, TCPMUX_ACK, sizeof( TCPMUX_ACK ) ) !=
                 sizeof( TCPMUX_ACK ) )
            {
                msg(LOG_ERR, "tcpmux_handler", "Ack write failed for %s.",
		    svc_name);
                exit(0);
            }
         }
         break;  /*  Time to get on with the service */
      }
      continue;  /*  Keep looking */
   }

   if ( u >= pset_count( SERVICES( ps ) ) )
   {
      if ( debug.on )
      {
         msg(LOG_DEBUG, "tcpmux_handler", "Service name %s not found.",
             svc_name);
      }
      exit(0);
   }

   if( SVC_WAITS( svc ) ) /* Service forks, so close it */
      Sclose(descriptor);

   server.svr_sp = sp;
   server.svr_conn = SERVER_CONNECTION(serp);
   nserp = server_alloc(&server);
   if( SC_IS_INTERNAL( scp ) ) {
      SC_INTERNAL(scp, nserp);
   } else {
      exec_server(nserp);
   }
}