Exemplo n.º 1
0
static void dgram_chargen( const struct server *serp )
{
   char            buf[ BUFFER_SIZE ] ;
   char            *p ;
   unsigned int    len ;
   union xsockaddr lsin ;
   socklen_t       sin_len = 0 ;
   int             fd      = SERVER_FD( serp ) ;
   unsigned int    left    = sizeof( buf ) ;
   const char     *func    = "dgram_chargen";

   if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
      sin_len = sizeof( struct sockaddr_in );
   else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
      sin_len = sizeof( struct sockaddr_in6 );

   if ( recvfrom( fd, buf, sizeof( buf ), 0, SA( &lsin ), &sin_len ) == -1 )
      return ;

#if BUFFER_SIZE < LINE_LENGTH+2
   bad_variable = 1 ;      /* this will cause a compilation error */
#endif

   for ( p = buf ; left > 2 ; left -= len, p += len )
   {
      len = min( LINE_LENGTH+2, left ) ;
      if ( generate_line( p, len ) == NULL )
         break ;
   }
   (void) sendto( fd, buf, p-buf, 0, SA( &lsin ), sin_len ) ;
}
Exemplo n.º 2
0
static status_e get_incoming_packet( struct intercept_s *ip, packet_s *pp )
{
   socklen_t from_len = 0;
   const char *func = "get_incoming_packet" ;

   if( SC_IPV4( SVC_CONF( SERVER_SERVICE( INT_SERVER( ip ) ) ) ) )
      from_len = sizeof( struct sockaddr_in );
   if( SC_IPV6( SVC_CONF( SERVER_SERVICE( INT_SERVER( ip ) ) ) ) )
      from_len = sizeof( struct sockaddr_in6 );

   for ( ;; )
   {
      int cc ;

      from_len = sizeof( pp->from ) ;
      cc = recvfrom( INT_REMOTE( ip ), pp->data, pp->size,
                                    0, SA( &pp->from ), &from_len ) ;
      if ( cc == -1 )
      {
         if ( errno != EINTR )
         {
            msg( LOG_ERR, func, "recvfrom error: %m" ) ;
            return( FAILED ) ;
         }
      }
      else if ( cc == 0 )
         return( FAILED ) ;
      else
      {
         pp->size = cc ;
         IDP( ip->int_priv )->received_packets++ ;
         break ;
      }
   }

   if ( from_len == 0 )
   {
      msg( LOG_ERR, func, "incoming packet had 0 length address" ) ;
      return( FAILED ) ;
   }
   
#ifdef DEBUG_UDPINT
   if ( debug.on )
      msg( LOG_DEBUG, func, "Received %d bytes from address: %s,%d",
         pp->size, xaddrname( &pp->from ), ntohs( xaddrport(&pp->from) ) );
#endif

   return( OK ) ;
}
Exemplo n.º 3
0
/*
 * Count the number of references to the specified service contained
 * in the specified table of servers; put the number of servers
 * in *countp
 */
static int count_refs( struct service *sp, pset_h servers, unsigned *countp )
{
   unsigned u ;
   struct server *serp ;
   int refs = 0 ;
   unsigned count = 0 ;

   for ( u = 0 ; u < pset_count( servers ) ; u++ )
   {
      serp = SERP( pset_pointer( SERVERS( ps ), u ) ) ;
      if ( SERVER_SERVICE( serp ) == sp )
      {
         refs++ ;
         count++ ;
      }
      if ( SERVER_CONNSERVICE( serp ) == sp )
         refs++ ;
      /*
       * XXX:   in the future we may want to check if the given service
       *         is any of the alternative services (currently only SPECIAL
       *         services can be alternative services and SPECIAL services
       *         are not included in the service table)
       */
   }
   *countp = count ;
   return( refs ) ;
}
Exemplo n.º 4
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);
}
Exemplo n.º 5
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);
}
Exemplo n.º 6
0
static void dgram_echo( const struct server *serp )
{
   char            buf[ DATAGRAM_SIZE ] ;
   union xsockaddr lsin;
   ssize_t             cc ;
   socklen_t       sin_len = 0;
   int             descriptor = SERVER_FD( serp ) ;

   if( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
      sin_len = sizeof( struct sockaddr_in );
   else if( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
      sin_len = sizeof( struct sockaddr_in6 );

   cc = recvfrom( descriptor, buf, sizeof( buf ), 0, (struct sockaddr *)( &lsin ), &sin_len ) ;
   if ( cc != (ssize_t)-1 ) {
      (void) sendto( descriptor, buf, (size_t)cc, 0, SA( &lsin ), sizeof( lsin ) ) ;
   }
}
Exemplo n.º 7
0
static void dgram_time( const struct server *serp )
{
   char     buf[ 1 ] ;
   unsigned char time_buf[4];
   union xsockaddr lsin ;
   socklen_t       sin_len = 0 ;
   int             fd      = SERVER_FD( serp ) ;
   const char     *func    = "dgram_daytime";

   if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
      sin_len = sizeof( struct sockaddr_in );
   else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
      sin_len = sizeof( struct sockaddr_in6 );

   if ( recvfrom( fd, buf, sizeof( buf ), 0, SA( &lsin ), &sin_len ) == -1 )
      return ;

   time_protocol( time_buf ) ;
   (void) sendto( fd, (char *) time_buf, 4, 0, SA( &lsin ), sin_len ) ;
}
Exemplo n.º 8
0
static void dgram_daytime( const struct server *serp )
{
   char            time_buf[ BUFFER_SIZE ] ;
   union xsockaddr lsin ;
   socklen_t       sin_len     = 0 ;
   unsigned int    buflen      = sizeof( time_buf ) ;
   int             descriptor  = SERVER_FD( serp ) ;
   const char     *func       = "dgram_daytime";

   if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
      sin_len = sizeof( struct sockaddr_in );
   else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
      sin_len = sizeof( struct sockaddr_in6 );

   if ( recvfrom( descriptor, time_buf, sizeof( time_buf ), 0,
            SA( &lsin ), &sin_len ) == -1 )
      return ;

   daytime_protocol( time_buf, &buflen ) ;
   
   (void) sendto( descriptor, time_buf, buflen, 0, SA(&lsin), sizeof( lsin ) ) ;
}
Exemplo n.º 9
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);
}
Exemplo n.º 10
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);
}
Exemplo n.º 11
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);
}
Exemplo n.º 12
0
/* This function gets called from child.c after we have been forked */
void redir_handler( struct server *serp )
{
   struct service *sp = SERVER_SERVICE( serp );
   struct service_config *scp = SVC_CONF( sp );
   int RedirDescrip = SERVER_FD( serp );
   int maxfd, num_read, num_wrote=0, ret=0;
   unsigned int sin_len = 0;
   unsigned long bytes_in = 0, bytes_out = 0;
   int no_to_nagle = 1;
   int on = 1, v6on;
   char buff[NET_BUFFER];
   fd_set rdfd, msfd;
   struct timeval *timep = NULL;
   const char *func = "redir_handler";
   union xsockaddr serveraddr ;

   if( signal(SIGPIPE, redir_sigpipe) == SIG_ERR ) 
      msg(LOG_ERR, func, "unable to setup signal handler");

   close_all_svc_descriptors();

   /* If it's a tcp service we are redirecting */
   if( scp->sc_protocol.value == IPPROTO_TCP )
   {
      memcpy(&serveraddr, scp->sc_redir_addr, sizeof(serveraddr));
      if( serveraddr.sa_in.sin_family == AF_INET ) {
         sin_len = sizeof( struct sockaddr_in );
         RedirServerFd = socket(AF_INET, SOCK_STREAM, 0);
       } else if( serveraddr.sa_in.sin_family == AF_INET6 ) {
         sin_len = sizeof( struct sockaddr_in6 );
         RedirServerFd = socket(AF_INET6, SOCK_STREAM, 0);
      } else {
         msg(LOG_ERR, func, "not a valid protocol. Use IPv4 or IPv6.");
         exit(0);
      }

      if( RedirServerFd < 0 )
      {
         msg(LOG_ERR, func, "cannot create socket: %m");
         exit(0);
      }

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

      }
      if( SC_KEEPALIVE( scp ) )
         if (setsockopt(RedirServerFd, SOL_SOCKET, SO_KEEPALIVE, 
                        (char *)&on, sizeof( on ) ) < 0 )
            msg(LOG_ERR, func, 
                "setsockopt SO_KEEPALIVE RedirServerFd failed: %m");
      
      if( serveraddr.sa_in.sin_family == AF_INET )
         serveraddr.sa_in.sin_port = htons(serveraddr.sa_in.sin_port);
      if( serveraddr.sa_in.sin_family == AF_INET6 )
         serveraddr.sa_in6.sin6_port = htons(serveraddr.sa_in6.sin6_port);

      if( connect(RedirServerFd, &serveraddr.sa, sin_len) < 0 )
      {
         msg(LOG_ERR, func, "can't connect to remote host %s: %m",
            xaddrname( &serveraddr ) );
         exit(0);
      }

      /* connection now established */

      if (setsockopt(RedirServerFd, IPPROTO_TCP, TCP_NODELAY, 
         (char *) &no_to_nagle, sizeof( on ) ) < 0) {

         msg(LOG_ERR, func, "setsockopt RedirServerFd failed: %m");
      }

      if (setsockopt(RedirDescrip, IPPROTO_TCP, TCP_NODELAY, 
         (char *) &no_to_nagle, sizeof( on ) ) < 0) {

         msg(LOG_ERR, func, "setsockopt RedirDescrip failed: %m");
      }

      maxfd = (RedirServerFd > RedirDescrip)?RedirServerFd:RedirDescrip;
      FD_ZERO(&msfd);
      FD_SET(RedirDescrip, &msfd);
      FD_SET(RedirServerFd, &msfd);

      while(1) {
         memcpy(&rdfd, &msfd, sizeof(rdfd));
         if (select(maxfd + 1, &rdfd, (fd_set *)0, (fd_set *)0, timep) <= 0) {
            /* place for timeout code, currently does not time out */
            break;
         }

         if (FD_ISSET(RedirDescrip, &rdfd)) {
            do {
               num_read = read(RedirDescrip,
                  buff, sizeof(buff));
               if (num_read == -1 && errno == EINTR)
                  continue;
               if (num_read <= 0)
                  goto REDIROUT;
               bytes_in += num_read;
            } while (num_read < 0);

            /* Loop until we have written everything
             * that was read */
            num_wrote = 0;
            while( num_wrote < num_read ) {
               ret = write(RedirServerFd,
                  buff + num_wrote,
                  num_read - num_wrote);
               if (ret == -1 && errno == EINTR)
                  continue;
               if (ret <= 0)
                  goto REDIROUT;
               num_wrote += ret;
            }
         }

         if (FD_ISSET(RedirServerFd, &rdfd)) {
            do {
               num_read = read(RedirServerFd,
                  buff, sizeof(buff));
               if (num_read == -1 && errno == EINTR)
                  continue;
               if (num_read <= 0)
                  goto REDIROUT;
               bytes_out += num_read;
            } while (num_read < 0);

            /* Loop until we have written everything
             * that was read */
            num_wrote = 0;
            while( num_wrote < num_read ) {
               ret = write(RedirDescrip,
                  buff + num_wrote,
                  num_read - num_wrote);
               if (ret == -1 && errno == EINTR)
                  continue;
               if (ret <= 0)
                  goto REDIROUT;
               num_wrote += ret;
            }
         }
      }
REDIROUT:
      if( M_IS_SET( (scp)->sc_log_on_success, LO_TRAFFIC ) ) {
         svc_logprint( SERVER_CONNSERVICE( serp ), "TRAFFIC",
                       "in=%lu(bytes) out=%lu(bytes)", bytes_in, bytes_out );
      }

      exit(0);
   }

   msg(LOG_ERR, func, 
   "redirect with any protocol other than tcp is not supported at this time.");
   exit(0);
}
Exemplo n.º 13
0
/*
 * Read data from the remote socket and send it to the appropriate local 
 * socket.
 * If this is a new connection, insert it in the connection table and
 * place its handle in *chpp.
 */
static void udp_remote_to_local( struct intercept_s *ip, channel_s **chpp )
{
   char               buf[ MAX_DATAGRAM_SIZE ] ;
   packet_s           packet ;
   channel_s          *chp ;
   bool_int           addr_checked ;

   *chpp = CHANNEL_NULL ;

   packet.data = buf ;
   packet.size = sizeof( buf ) ;
   if ( get_incoming_packet( ip, &packet ) == FAILED )
      return ;

   chp = int_lookupconn( ip, &packet.from, &addr_checked ) ;
   if ( chp == CHANNEL_NULL )
   {
      struct server      *serp = INT_SERVER( ip ) ;
      struct service    *sp = SERVER_SERVICE( serp ) ;
      connection_s      *cop = SERVER_CONNECTION( serp ) ;

      if ( ( chp = int_newconn( ip, &packet.from, INT_REMOTE( ip ) ) ) == NULL )
         return ;

      CONN_SETADDR( cop, &packet.from ) ;      /* for logging */

      if ( INTERCEPT( ip ) )
      {
         mask_t check_mask ;
         access_e result ;

         M_OR( check_mask, XMASK( CF_ADDRESS ), XMASK( CF_TIME ) ) ;
         result = access_control( sp, cop, &check_mask ) ;

         if ( result != AC_OK )
         {
            svc_log_failure( sp, cop, result ) ;
            chp->ch_state = BAD_CHANNEL ;
            return ;
         }
      }
      
      /*
       * Since we don't distinguish ports, there is no point to log
       * another successful attempt from the same address
       */
      if ( ! addr_checked )
         svc_log_success( sp, cop, SERVER_PID( serp ) ) ;
         
      *chpp = chp ;
   }
   else if ( chp->ch_state == BAD_CHANNEL )
      return ;
   
#ifdef DEBUG_UDPINT
   if ( debug.on )
      msg( LOG_DEBUG, "udp_remote_to_local",
               "sending %d bytes to server on port %d",
                     packet.size, ntohs( INT_LOCALADDR( ip )->sin_port ) ) ;
#endif

   send_data( chp->ch_local_socket,
         packet.data, packet.size, NULL ) ;
}
Exemplo n.º 14
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);
   }
}
Exemplo n.º 15
0
Arquivo: child.c Projeto: aosm/xinetd
/*
 * This function is running in the new process
 */
void exec_server( const struct server *serp )
{
   const struct service_config *scp = SVC_CONF( SERVER_SERVICE( serp ) ) ;
   struct rlimit rl ;
   int fd ;
   int descriptor = SERVER_FD( serp ) ;
   const char *server = SC_SERVER( scp ) ;
   const char *func = "exec_server" ;

   /*
    * The following code solves a problem with post-version-4.3
    * Ultrix systems (the bug was reported, and a fix was provided by
    * [email protected]; a slightly modified version of this
    * fix is included here).
    *
    * If this is a 'nowait' service, we pass the service descriptor
    * to the server. Note that we have set the close-on-exec flag
    * on all service descriptors. It is unclear whether the dup2()
    * will create a descriptor with the close-on-exec flag set,
    * so we explicitly clear the flag (since we are doing this
    * after the fork, it does not affect the descriptor of the
    * parent process).
    */
   if ( fcntl( descriptor, F_SETFD, 0 ) == -1 )
      msg( LOG_WARNING, func,
         "fcntl( %d, clear close-on-exec ) failed: %m", descriptor ) ;

   if ( debug.on )
      msg( LOG_DEBUG, func, "duping %d", descriptor ) ;

   for ( fd = 0 ; fd <= MAX_PASS_FD ; fd++ )
   {
      if ( dup2( descriptor, fd ) == -1 )
      {
         msg( LOG_ERR, func,
               "dup2( %d, %d ) failed: %m", descriptor, fd ) ;
         _exit( 1 ) ;
      }
   }


#ifdef RLIMIT_NOFILE
   rl.rlim_max = ps.ros.orig_max_descriptors ;
   rl.rlim_cur = ps.ros.max_descriptors ;
   (void) setrlimit( RLIMIT_NOFILE, &rl ) ;
#endif
#ifdef RLIMIT_AS
   if (SC_RLIM_AS (scp))
   {
      rl.rlim_cur = SC_RLIM_AS( scp );
      rl.rlim_max = SC_RLIM_AS( scp );
      (void) setrlimit( RLIMIT_AS, &rl );
   }
#endif
#ifdef RLIMIT_CPU
   if (SC_RLIM_CPU (scp))
   {
      rl.rlim_cur = SC_RLIM_CPU( scp );
      rl.rlim_max = SC_RLIM_CPU( scp );
      (void) setrlimit( RLIMIT_CPU, &rl );
   }
#endif
#ifdef RLIMIT_DATA
   if (SC_RLIM_DATA (scp))
   {
      rl.rlim_cur = SC_RLIM_DATA( scp );
      rl.rlim_max = SC_RLIM_DATA( scp );
      (void) setrlimit( RLIMIT_DATA, &rl );
   }
#endif
#ifdef RLIMIT_RSS
   if (SC_RLIM_RSS (scp))
   {
      rl.rlim_cur = SC_RLIM_RSS( scp );
      rl.rlim_max = SC_RLIM_RSS( scp );
      (void) setrlimit( RLIMIT_RSS, &rl );
   }
#endif
#ifdef RLIMIT_STACK
   if (SC_RLIM_STACK (scp))
   {
      rl.rlim_cur = SC_RLIM_STACK( scp );
      rl.rlim_max = SC_RLIM_STACK( scp );
      (void) setrlimit( RLIMIT_STACK, &rl );
   }
#endif

   (void) Sclose( descriptor ) ;

#ifndef solaris
   no_control_tty() ;
#endif

   msg_suspend() ;

   (void) execve( server, SC_SERVER_ARGV( scp ),
             env_getvars( SC_ENV( scp )->env_handle ) ) ;

   /*
    * The exec failed. Log the error and exit.
    */
   msg_resume() ;
   msg( LOG_ERR, func, "execv( %s ) failed: %m", server ) ;
   _exit( 0 ) ;
}
Exemplo n.º 16
0
Arquivo: child.c Projeto: aosm/xinetd
/*
 * This function is invoked in a forked process to run a server. 
 * If the service is internal the appropriate function is invoked
 * otherwise the server program is exec'ed.
 * This function also logs the remote user id if appropriate
 */
void child_process( struct server *serp )
{
   struct service          *sp  = SERVER_SERVICE( serp ) ;
   connection_s            *cp  = SERVER_CONNECTION( serp ) ;
   struct service_config   *scp = SVC_CONF( sp ) ;
   const char              *func = "child_process" ;

   signal_default_state();

   if ((signals_pending[0] >= 0 && Sclose(signals_pending[0])) ||
       (signals_pending[1] >= 0 && Sclose(signals_pending[1])))
   {
      msg(LOG_ERR, func, "Failed to close the signal pipe: %m");
      _exit(1);
   }
   signals_pending[0] = -1;
   signals_pending[1] = -1;

   Sclose(0);
   Sclose(1);
   Sclose(2);


#ifdef DEBUG_SERVER
   if ( debug.on )
   {
      msg( LOG_DEBUG, func, "Process %d is sleeping", getpid() ) ;
      sleep( 10 ) ;
   }
#endif

   if ( ! SC_IS_INTERCEPTED( scp ) )
   {
      set_credentials( scp ) ;
      if ( SC_SPECIFIED( scp, A_NICE ) )
         (void) nice( SC_NICE( scp ) ) ;
   }

   if ( svc_child_access_control(sp, cp) != OK )
      exit(0);

   if ( SERVER_LOGUSER( serp ) )
   {
      unsigned   timeout ;
      idresult_e result ;
      
      /*
       * We use LOGUSER_SUCCESS_TIMEOUT unless the service requires
       * identification, in which case we use an infinite timeout
       */
      timeout = SC_MUST_IDENTIFY( scp ) ? 0 : LOGUSER_SUCCESS_TIMEOUT ;
      result = log_remote_user( serp, timeout ) ;

      if ( result != IDR_OK && SC_MUST_IDENTIFY( scp ) )
      {
         svc_logprint( sp, NOID_ENTRY, "%s %s",
                  conn_addrstr( SERVER_CONNECTION( serp ) ),
                     idresult_explain( result ) ) ;
         _exit( 0 ) ;
      }
   }

#ifdef HAVE_SESSIONCREATE
   if ( scp->sc_sessioncreate == YES ) 
   {
      if ( SessionCreate(0, sessionHasTTY|sessionIsRemote) != noErr )
         svc_logprint( sp, "SessionCreate", "SessionCreate() failed!" );
   }
#endif

   /* this is where the server gets executed  -bbraun */
   if ( ! SC_IS_INTERNAL( scp ) )
   {
      if( scp->sc_redir_addr != NULL )
      {
         redir_handler( serp );
      }
      else
      {
#if defined(HAVE_SETENV)
         char buff[1024];

         strx_sprint(buff, sizeof(buff)-1, "REMOTE_HOST=%s", conn_addrstr(cp));
         if( env_addstr(SC_ENV(scp)->env_handle, buff) != ENV_OK ) {
            msg( LOG_ERR, func, "Error adding REMOTE_HOST variable for %s: %m", SC_NAME(scp) );
            _exit( 1 ) ;
         }
#endif
         exec_server( serp ) ;
      }
   }
   else
   {
      char name[ 180 ] ;
      /*
       * We don't bother to disassociate from the controlling terminal
       *   (we have a controlling terminal only if debug.on is TRUE)
       *
       * Also, for interceptor processes, we give them the name:
       *            <program_name> <service-id> interceptor
       */
      if ( SC_IS_INTERCEPTED( scp ) )
         strx_print( INT_NULL, name, sizeof( name ) - 1,
                           "%s %s interceptor", program_name, SC_ID( scp ) ) ;
      else
      {
         int namelen = sizeof( name ) - 1 ;      /* leave space for the NUL */
         char host[NI_MAXHOST];
         size_t hostlen = NI_MAXHOST;
         socklen_t addrlen = 0;
         union xsockaddr *sinp = CONN_XADDRESS(SERVER_CONNECTION(serp));
         int len;

         if( sinp == NULL )
            exit(0);

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

         len = strx_nprint(name, namelen, "(%s service) %s", program_name,
            SC_ID( scp ) ) ;

         if( getnameinfo( SA(sinp), addrlen, host, hostlen, NULL, 0, 0) != 0 )
               strcpy(host, "unknown");

         if ( SC_IPV6(scp) && SC_ACCEPTS_CONNECTIONS( scp ) && 
               !IN6_IS_ADDR_UNSPECIFIED(&sinp->sa_in6.sin6_addr) )
            strx_print( INT_NULL, &name[ len ], namelen - len, " %s" , host ) ;
         if ( SC_IPV4(scp) && SC_ACCEPTS_CONNECTIONS( scp ) )
            strx_print( INT_NULL, &name[ len ], namelen - len, " %s", host ) ;
      }
      rename_process( name ) ;
      SVC_INTERNAL( sp, serp ) ;
   }
   _exit( 0 ) ;
   /* NOTREACHED */
}