Beispiel #1
0
/*
 * Remove all NULL pointers from a pset
 */
void pset_compact( register pset_h pset )
{
	register unsigned u ;

	for ( u = 0 ; u < pset_count( pset ) ; )
	{
		POINTER ptr = pset_pointer( pset, u );
		if ( ptr != NULL )
			u++ ;
		else
			pset_delete( pset, ptr ) ;
	}

	/* See if we can reclaim some memory, make sure we are 2 below for some hysteresis */
	if ((int)( pset->max - pset->alloc_step - 2) > (int)pset_count( pset ))
	{	/* This rounds up to the next unit of steps */
		POINTER *new_ptrs ;
		unsigned new_max = ((pset_count( pset ) / pset->alloc_step) + 1)*pset->alloc_step;

		new_ptrs = (POINTER *) realloc(
								(char *)pset->ptrs, new_max * sizeof( POINTER ) ) ;
		if ( new_ptrs == NULL )
			return;
		pset->max = new_max ;
		pset->ptrs = new_ptrs ;
	}
}
Beispiel #2
0
static void scrub_global_access_list( void )
{
   unsigned count;
   const char *func = "scrub_global_no_access_list";

   if ( global_no_access == NULL )
      count = 0;
   else
      count = pset_count( global_no_access );

   if ( count )
   {
      int found_one = 0;
      unsigned u;
      time_t nowtime = time(NULL);

      for (u=0; u < count; u++)
      {
         char *exp_time;
         time_t stored_time;
	 
	 exp_time = pset_pointer( global_no_access_time, u ) ;
         stored_time = atol(exp_time);

	 if (stored_time == -1)   /* never let them off   */
	    continue;

	 if (difftime(nowtime, (time_t)stored_time) >= 0.0)
	 {
	    __pset_pointer ptr;

            pset_pointer(global_no_access, u) = NULL;
            ptr = global_no_access_time->ptrs[ u ];
            free(ptr);
            pset_pointer(global_no_access_time, u ) = NULL;
            found_one = 1;
         }
      }
      if (found_one)
      {
         pset_compact( global_no_access );
         pset_compact( global_no_access_time );
	 msg(LOG_INFO, func, 
	    "At least 1 DENY_TIME has expired, global_no_access list updated");
      }

      /* If there's still more on the list, start another callback. */
      count = pset_count( global_no_access );
      if ( count )
         timer_id = xtimer_add( scrub_global_access_list, 60 );
      else
      {
         timer_id = 0;
	 msg(LOG_INFO, func, 
	          "global_no_access list is empty.");
      }
   }
}
Beispiel #3
0
/* xtimer_poll:
 * Traverses the pset_h of timers, and executes the callback for expired
 * timers.  Timers that are expired, and have their callback executed
 * are removed from the list of timers. 
 */
int xtimer_poll(void)
{
	unsigned int i;
	
	if( xtimer_list == NULL )
		return(0);

	for( i = 0; i < pset_count( xtimer_list ); i++ ) {
		xtime_h *cur_timer = pset_pointer( xtimer_list, i );
		time_t cur_time    = time(NULL);

		/* The list is sorted, low to high.  If there's no
		 * timers left, return.
		 */
		if( cur_timer->when > cur_time ) {
			return(0);
		}
		cur_timer->timerfunc();
		pset_delete( xtimer_list, cur_timer );
		free(cur_timer);
		i--;
		cur_timer = NULL;
	}

	return(0);
}
Beispiel #4
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 ) ;
}
Beispiel #5
0
/*
 * Remove an element from a pset
 */
void psi_remove( psi_h iter )
{
	if ( iter->current < pset_count( iter->pset ) )
	{
		pset_remove_index( iter->pset, iter->current ) ;
		iter->step = 0;
	}
}
Beispiel #6
0
/* They hit a real server...note, this is likely to be a child process. */
status_e check_sensor( const union xsockaddr *addr)
{

   if ( (global_no_access) && pset_count( global_no_access ) )
   {
      if (addrlist_match( global_no_access, SA(addr)))
         return FAILED;
   }
   return OK;
}
Beispiel #7
0
/*
 * Apply a function to all pointers of a pset
 */
void pset_apply( register pset_h pset, void (*func)(), register void *arg )
{
	register unsigned u ;

	for ( u = 0 ; u < pset_count( pset ) ; u++ )
		if ( arg )
			(*func)( arg, pset_pointer( pset, u ) ) ;
		else
			(*func)( pset_pointer( pset, u ) ) ;
}
Beispiel #8
0
static void dump_services( int fd )
{
   unsigned u ;

   /*
    * Dump the current configuration (services + defaults)
    */
   Sprint( fd, "Services + defaults:\n" ) ;
   sc_dump( DEFAULTS( ps ), fd, 0, TRUE ) ;

   for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
      svc_dump( SP( pset_pointer( SERVICES( ps ), u ) ), fd ) ;
}
Beispiel #9
0
void ti_dump( pset_h iset, int fd )
{
   unsigned u ;

   for ( u = 0 ; u < pset_count( iset ) ; u++ )
   {
      struct time_interval *tip = TIP( pset_pointer( iset, u ) ) ;

      Sprint( fd, " %02d:%02d-%02d:%02d",
         tip->min_start / 60, tip->min_start % 60,
         tip->min_end / 60, tip->min_end % 60 ) ;
   }
}
Beispiel #10
0
/*
 * Returns only if there is an I/O error while communicating with the server
 */
static void di_mux(void)
{
   struct intercept_s   *ip = &dgram_intercept_state ;
   fd_set                     socket_mask ;
   int                        mask_max ;

   FD_ZERO( &socket_mask ) ;
   FD_SET( INT_REMOTE( ip ), &socket_mask ) ;
   mask_max = INT_REMOTE( ip ) ;

   for ( ;; )
   {
      unsigned u ;
      channel_s *chp ;
      fd_set read_mask ;
      int n_ready ;

      read_mask = socket_mask ;
      n_ready = int_select( mask_max+1, &read_mask ) ;

      if ( n_ready == -1 )
         return ;
      
      if ( FD_ISSET( INT_REMOTE( ip ), &read_mask ) )
      {
         udp_remote_to_local( ip, &chp ) ;
         if ( chp != NULL )
         {
            FD_SET( chp->ch_local_socket, &socket_mask ) ;
            if ( chp->ch_local_socket > mask_max )
               mask_max = chp->ch_local_socket ;
         }
         if ( --n_ready == 0 )
            continue ;
      }

      for ( u = 0 ; u < pset_count( INT_CONNECTIONS( ip ) ) ; u++ )
      {
         chp = CHP( pset_pointer( INT_CONNECTIONS( ip ), u ) ) ;

         if ( FD_ISSET( chp->ch_local_socket, &read_mask ) )
         {
            if ( udp_local_to_remote( chp ) == FAILED )
               return ;
            if ( --n_ready == 0 )
               break ;
         }
      }
   }
}
Beispiel #11
0
	/* Change the sets to arrays. */
	foreach_irp_irg(i, irg) {
		pset *callee_set = (pset *)irg->callees;
		size_t count = pset_count(callee_set);
		irg->callees = NEW_ARR_F(cg_callee_entry *, count);
		irg->callee_isbe = NULL;
		size_t j = 0;
		foreach_pset(callee_set, cg_callee_entry, callee) {
			irg->callees[j++] = callee;
		}
		del_pset(callee_set);
		assert(j == count);

		pset *caller_set = (pset *)irg->callers;
		count = pset_count(caller_set);
		irg->callers = NEW_ARR_F(ir_graph *, count);
		irg->caller_isbe =  NULL;
		j = 0;
		foreach_pset(caller_set, ir_graph, c) {
			irg->callers[j++] = c;
		}
		del_pset(caller_set);
		assert(j == count);
	}
Beispiel #12
0
/* xtimer_nexttime:
 * Returns the number of seconds until the next timer expires.
 * Returns -1 when no timers are active.
 */
time_t xtimer_nexttime(void)
{
	time_t ret;

	if(xtimer_list == NULL)
		return -1;

	if( pset_count(xtimer_list) == 0 )
		return -1;

	ret = ((xtime_h *)pset_pointer(xtimer_list, 0))->when - time(NULL) ;
	if( ret < 0 )
		ret = 0;
	return( ret );
}
Beispiel #13
0
/* xtimer_remove:
 * Removes a timer from the list of timers.  Takes the timer id as an argument
 * Returns:
 * Success: 0
 * Failure: -1
 */
int xtimer_remove(int xtid)
{
	unsigned int i;
	int ret = -1;

	for( i = 0; i < pset_count( xtimer_list ); i++ ) {
		xtime_h *cur_timer = pset_pointer( xtimer_list, i );
		if( cur_timer->xtid == xtid ) {
			pset_delete( xtimer_list, cur_timer );
			free( cur_timer );
			cur_timer = NULL;
			ret = 0;
		}
	}

	return(ret);
}
Beispiel #14
0
/*
 * Returns TRUE if the current time is within at least one of the intervals
 */
bool_int ti_current_time_check( const pset_h intervals )
{
   time_t      current_time ;
   unsigned    u ;
   int16_t     min_current ;
   struct tm   *tmp ;

   (void) time( &current_time ) ;
   tmp = localtime( &current_time ) ;
   min_current = tmp->tm_hour * 60 + tmp->tm_min ;

   for ( u = 0 ; u < pset_count( intervals ) ; u++ )
   {
      struct time_interval *tip ;
      
      tip = TIP( pset_pointer( intervals, u ) ) ;
      if ( IN_RANGE( min_current, tip->min_start, tip->min_end ) )
         return( TRUE ) ;
   }
   return( FALSE ) ;
}
Beispiel #15
0
/* xtimer_add:
 * Adds a timer to the pset_h of timers, and sorts the timer list (least time
 * remaining first).
 * Return values:
 * Success: the timer ID which can be used to later remove the timer (>0)
 * Failure: -1
 */
int xtimer_add( void (*func)(void), time_t secs )
{
	xtime_h *new_xtimer = NULL;
	time_t tmptime;
	unsigned count;

	if( xtimer_list == NULL ) {
		if( xtimer_init() < 0 )
			return -1;
	}

	new_xtimer = (xtime_h *)malloc(sizeof(xtime_h));
	if( new_xtimer == NULL ) {
		return -1;
	}

	tmptime = time(NULL);
	if( tmptime == -1 ) {
		free( new_xtimer );
		return -1;
	}
	
	new_xtimer->timerfunc = func;
	new_xtimer->when =  tmptime + secs;

	if( (count = pset_count( xtimer_list )) == 0 ) {
	   new_xtimer->xtid = 1;
	} else {
	   new_xtimer->xtid = ((xtime_h *)(pset_pointer(xtimer_list, count-1)))->xtid + 1;
	}

	if( pset_add( xtimer_list, new_xtimer ) == NULL ) {
		free( new_xtimer );
		return -1;
	}
		
	pset_sort( xtimer_list, xtimer_compfunc );
	
	return(new_xtimer->xtid);
}
Beispiel #16
0
static status_e update_env_with_strings( env_h env, pset_h strings )
{
   unsigned u ;
   const char *func = "update_env_with_strings" ;

   for ( u = 0 ; u < pset_count( strings ) ; u++ )
   {
      char *p = (char *) pset_pointer( strings, u ) ;

      if ( env_addstr( env, p ) == ENV_ERR )
         switch ( env_errno )
         {
            case ENV_ENOMEM:
               out_of_memory( func ) ;
               return( FAILED ) ;
            
            case ENV_EBADSTRING:
               msg( LOG_ERR, func, "Bad environment string: %s", p ) ;
               break ;
         }
   }
   return( OK ) ;
}
Beispiel #17
0
static status_e make_env_from_vars( struct environment *ep, 
                                     env_h env, 
                                     pset_h vars )
{
   env_h               new_env ;
   char               *varname ;
   unsigned            u ;
   const char         *func = "make_env_from_vars" ;

   if ( ( new_env = env_create( ENV_NULL ) ) == ENV_NULL )
   {
      out_of_memory( func ) ;
      return( FAILED ) ;
   }
   
   for ( u = 0 ; u < pset_count( vars ) ; u++ )
   {
      varname = (char *) pset_pointer( vars, u ) ;
      if ( env_addvar( new_env, env, varname ) == ENV_ERR )
         switch ( env_errno )
         {
            case ENV_EBADVAR:
               msg( LOG_ERR, func, "Unknown variable %s", varname ) ;
               break ;
            
            case ENV_ENOMEM:
               out_of_memory( func ) ;
               env_destroy( new_env ) ;
               return( FAILED ) ;
         }
   }

   ep->env_type = CUSTOM_ENV ;
   ep->env_handle = new_env ;
   return( OK ) ;
}
Beispiel #18
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" ) ;
}
Beispiel #19
0
/*
 * This function runs in the parent context and updates the global_no_access
 * list. 
 */
void process_sensor( const struct service *sp, const union xsockaddr *addr)
{
   const char *func = "process_sensor";

   if (SC_DENY_TIME(SVC_CONF(sp)) != 0)   /* 0 simply logs it   */
   {
      if ( pset_count( global_no_access ) < MAX_GLOBAL_NO_ACCESS)
      {
         int item_matched = addrlist_match( global_no_access, SA(addr) );

	 if ( item_matched == 0)
	 {   /* no match...adding to the list   */
            char *dup_addr = new_string(xaddrname( addr ) );

	    if (dup_addr == NULL )
               return ;

	    if (addrlist_add(global_no_access, dup_addr) == FAILED)
               msg(LOG_ERR, func,
                  "Failed adding %s to the global_no_access list", dup_addr);
            else
            {
               time_t nowtime;
               char time_buf[40], *tmp;

	       nowtime = time(NULL);
	       msg(LOG_CRIT, func,
	           "Adding %s to the global_no_access list for %d minutes",
	            dup_addr, SC_DENY_TIME(SVC_CONF(sp)));

	       if (SC_DENY_TIME(SVC_CONF(sp)) == -1)
                    strcpy(time_buf, "-1");
               else
                    strx_nprint(time_buf, 38, "%ld",
                       (time_t)nowtime+(60*SC_DENY_TIME(SVC_CONF(sp))));

	       tmp = new_string(time_buf);
               if (tmp != NULL)
               {
                  if (pset_add(global_no_access_time, tmp) == NULL)
                  {
                     msg(LOG_ERR, func,
                         "Failed adding %s to the global_no_access_time list. "
                         "global_no_access list is broken, xinetd needs "
			 "restarting.", dup_addr);
                 /* ideally, we should rollback the previous addr addition.   */
                  }
               }
	       if (pset_count(global_no_access) && (timer_id == 0) )
                  timer_id = xtimer_add( scrub_global_access_list, 60 );
            }
            free(dup_addr);
         }
         else
	 {
	    /* Here again, eh?...update time stamp. */
            char *exp_time;
	    time_t stored_time;

	    item_matched--; /* Is # plus 1, to even get here must be >= 1 */
            exp_time = pset_pointer( global_no_access_time, item_matched ) ;
            if (exp_time == NULL)
               return ;

            if ( parse_base10(exp_time, (int *)&stored_time) )
            {  /* if never let them off, bypass */
               if (stored_time != -1)
               {
                  time_t nowtime, new_time;

                  nowtime = time(NULL);
                  new_time = (time_t)nowtime+(60*SC_DENY_TIME(SVC_CONF(sp)));                     if (difftime(new_time, (time_t)stored_time) > 0.0)
	          {   /* new_time is longer save it   */
		     char time_buf[40], *new_exp_time;

		     strx_nprint(time_buf, 38, "%ld", (long)new_time);
		     new_exp_time = new_string(time_buf);
		     if ( new_exp_time )
		     {
		        free(exp_time);
			global_no_access_time->ptrs[ 
                        (unsigned)item_matched ] = new_exp_time;
                     }
                  }
               }
            }
         }
      }
      else
         msg(LOG_ERR, func, "Maximum global_no_access count reached.");
   }
}
Beispiel #20
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);
   }
}
Beispiel #21
0
static int get_next_inet_entry( int fd, pset_h sconfs, 
                          struct service_config *defaults)
{
   char *p;
   str_h strp;
   char *line = next_line(fd);
   struct service_config *scp;
   unsigned u, i;
   const char *func = "get_next_inet_entry";
   char *name = NULL, *rpcvers = NULL, *rpcproto = NULL;
   char *group, *proto, *stype;
   const struct name_value *nvp;
   struct protoent *pep ;
   struct passwd *pw ;
   struct group *grp ;
   const char *dot = ".";
   const char *slash = "/";
   pset_h args;
   
   if( line == CHAR_NULL )
      return -2;

   strp = str_parse( line, " \t", STR_RETURN_ERROR, INT_NULL ) ;
   if( strp == NULL )
   {
      parsemsg( LOG_CRIT, func, "inetd.conf - str_parse failed" ) ;
      return( -1 ) ;
   }

   if( (args = pset_create(10,10)) == NULL )
   {
      out_of_memory(func);
      return -1;
   }

   /* Break the line into components, based on spaces */
   while( (p = str_component( strp )) )
   {
      if( pset_add(args, p) == NULL )
      {
         parsemsg( LOG_CRIT, func, ES_NOMEM );
         pset_destroy(args);
         return -1;
      }
   }
   str_endparse( strp );

   /* get the service name */
   name = new_string((char *)pset_pointer( args, 0 ));
   if( name == NULL ) {
      parsemsg( LOG_ERR, func, "inetd.conf - Invalid service name" );
      pset_destroy(args);
      return -1;
   }

   /* Check to find the '/' for specifying RPC version numbers */
   if( (rpcvers = strstr(name, slash)) != NULL ) {
      *rpcvers = '\0';
      rpcvers++;
   }

   scp = sc_alloc( name );
   if( scp == NULL )
   {
      pset_destroy(args);
      free( name );
      return -1;
   }
   /*
    * sc_alloc makes its own copy of name. At this point, sc_alloc worked
    * so we will free our copy to avoid leaks.
    */
   free( name );

   /* Replicate inetd behavior in this regard.  Also makes sure the
    * service actually works on system where setgroups(0,NULL) doesn't
    * work.
    */
   SC_GROUPS(scp) = YES;
   SC_SPECIFY( scp, A_GROUPS );

   /* Get the socket type (stream dgram) */
   stype = (char *)pset_pointer(args, 1);
   if( stype == NULL ) {
      parsemsg( LOG_ERR, func, "inetd.conf - Invalid socket type" );
      pset_destroy(args);
      sc_free(scp);
      return -1;
   }
   nvp = nv_find_value( socket_types, stype );
   if( nvp == NULL )
   {
      parsemsg( LOG_ERR, func, "inetd.conf - Bad socket type: %s", p);
      pset_destroy(args);
      sc_free(scp);
      return -1;
   }

   SC_SOCKET_TYPE(scp) = nvp->value;

   /* Get the protocol type */
   proto = (char *)pset_pointer(args,2);
   if( strstr(proto, "rpc") != NULL )
   {
      int rpcmin, rpcmax;
      struct rpc_data *rdp = SC_RPCDATA( scp ) ;

      if( rpcvers == NULL ) {
         pset_destroy(args);
         sc_free(scp);
         return -1;
         /* uh oh */
      }

      p = strchr(rpcvers, '-');
      if( p && parse_int(rpcvers, 10, '-', &rpcmin) == 0 ) {
         if( parse_base10(p + 1, &rpcmax) || rpcmin > rpcmax ) {
            pset_destroy(args);
            sc_free(scp);
            return -1;
         }
      } else {
         if( parse_base10(rpcvers, &rpcmin) ) {
            pset_destroy(args);
            sc_free(scp);
            return -1;
         }

         rpcmax = rpcmin;
      }

      /* now have min and max rpc versions */
      rdp->rd_min_version = rpcmin;      
      rdp->rd_max_version = rpcmax;      

      rpcproto = strstr(proto, slash);
      if( rpcproto == NULL ) {
         parsemsg( LOG_ERR, func, "inetd.conf - bad rpc version numbers" );
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }
      *rpcproto = '\0';
      rpcproto++;
      proto = rpcproto;

      /* Set the RPC type field */
      nvp = nv_find_value( service_types, "RPC" );
      if ( nvp == NULL )
      {
         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }

      M_SET(SC_TYPE(scp), nvp->value);
   }
   if ( ( pep = getprotobyname( proto ) ) == NULL )
   {
      parsemsg( LOG_ERR, func, "inetd.conf - Protocol %s not in /etc/protocols",
	        proto ) ;
      pset_destroy(args);
      sc_free(scp);
      return -1;
   }

   SC_PROTONAME(scp) = new_string( proto ) ;
   if ( SC_PROTONAME(scp) == NULL )
   {
      out_of_memory( func ) ;
      pset_destroy(args);
      sc_free(scp);
      return -1;
   }
   SC_PROTOVAL(scp) = pep->p_proto;
   SC_SPECIFY(scp, A_PROTOCOL);

   /* Get the wait attribute */
   p = (char *)pset_pointer(args, 3);
   if ( p == NULL ) {
      parsemsg( LOG_ERR, func, "inetd.conf - No value specified for wait" );
      sc_free(scp);
      return -1;
   }
   if ( EQ( p, "wait" ) )
      SC_WAIT(scp) = YES ;
   else if ( EQ( p, "nowait" ) )
      SC_WAIT(scp) = NO ;
   else
      parsemsg( LOG_ERR, func, "inetd.conf - Bad value for wait: %s", p ) ;

   /* Get the user to run as */
   p = (char *)pset_pointer(args, 4);
   if ( p == NULL ) {
      parsemsg( LOG_ERR, func, "inetd.conf - No value specified for user" );
      sc_free(scp);
      return -1;
   }
   if( (group = strstr(p, dot)) )
   {
      *group = '\0';
      group++;
   
      grp = (struct group *)getgrnam( (char *)group ) ;
      if ( grp == NULL )
      {
         parsemsg( LOG_ERR, func, "inetd.conf - Unknown group: %s", group ) ;
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }   

      SC_GID(scp) = ((struct group *)grp)->gr_gid;
      SC_SPECIFY( scp, A_GROUP );
   }

   pw = getpwnam( p );
   if ( pw == NULL )
   {
      parsemsg( LOG_ERR, func, "inetd.conf - Unknown user: %s", p ) ;
      pset_destroy(args);
      sc_free(scp);
      return -1;
   }
   str_fill( pw->pw_passwd, ' ' );
   SC_UID(scp) = pw->pw_uid;
   SC_USER_GID(scp) = pw->pw_gid;

   /* Get server name, or flag as internal */
   p = (char *)pset_pointer(args, 5);
   if ( p == NULL ) {
      parsemsg( LOG_ERR, func, "inetd.conf - No value specified for user" );
      sc_free(scp);
      return -1;
   }
   if( EQ( p, "internal" ) ) 
   {
      nvp = nv_find_value( service_types, "INTERNAL" );
      if ( nvp == NULL )
      {
         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }

      M_SET(SC_TYPE(scp), nvp->value);

      if( EQ( SC_NAME(scp), "time" ) ) {
         if( EQ( proto, "stream" ) )
            SC_ID(scp) = new_string("time-stream");
         else
            SC_ID(scp) = new_string("time-dgram");
      }

      if( EQ( SC_NAME(scp), "daytime" ) ) {
         if( EQ( proto, "stream" ) )
            SC_ID(scp) = new_string("daytime-stream");
         else
            SC_ID(scp) = new_string("daytime-dgram");
      }

      if( EQ( SC_NAME(scp), "chargen" ) ) {
         if( EQ( proto, "stream" ) )
            SC_ID(scp) = new_string("chargen-stream");
         else
            SC_ID(scp) = new_string("chargen-dgram");
      }

      if( EQ( SC_NAME(scp), "echo" ) ) {
         if( EQ( proto, "stream" ) )
            SC_ID(scp) = new_string("echo-stream");
         else
            SC_ID(scp) = new_string("echo-dgram");
      }

      if( EQ( SC_NAME(scp), "discard" ) ) 
      {
         parsemsg(LOG_WARNING, func, 
		  "inetd.conf - service discard not supported");
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }
   }
   else
   {
      SC_SERVER(scp) = new_string( p );
      if ( SC_SERVER(scp) == NULL )
      {
         out_of_memory( func ) ;
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }
      SC_SPECIFY( scp, A_SERVER);

      /* Get argv */ 
      SC_SERVER_ARGV(scp) = (char **)argv_alloc(pset_count(args)+1);

      for( u = 0; u < pset_count(args)-6 ; u++ )
      {
         p = new_string((char *)pset_pointer(args, u+6));
         if( p == NULL )
         {
            for ( i = 1 ; i < u ; i++ )
               free( SC_SERVER_ARGV(scp)[i] );
            free( SC_SERVER_ARGV(scp) );
            pset_destroy(args);
            sc_free(scp);
            return -1;
         }
         SC_SERVER_ARGV(scp)[u] = p;
      }
      /* Set the reuse flag, as this is the default for inetd */
      nvp = nv_find_value( service_flags, "REUSE" );
      if ( nvp == NULL )
      {
         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }
      M_SET(SC_XFLAGS(scp), nvp->value);

      /* Set the NOLIBWRAP flag, since inetd doesn't have libwrap built in */
      nvp = nv_find_value( service_flags, "NOLIBWRAP" );
      if ( nvp == NULL )
      {
         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }
      M_SET(SC_XFLAGS(scp), nvp->value);
   
      /* Set the NAMEINARGS flag, as that's the default for inetd */
      nvp = nv_find_value( service_flags, "NAMEINARGS" );
      if ( nvp == NULL )
      {
         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
         pset_destroy(args);
         sc_free(scp);
         return (-1);
      }
      M_SET(SC_XFLAGS(scp), nvp->value);
      SC_SPECIFY( scp, A_SERVER_ARGS );

      if ( (SC_ID(scp) = new_string( SC_NAME(scp) )) )
         SC_PRESENT( scp, A_ID ) ;
      else
      {
         out_of_memory( func ) ;
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }
   }
   
   SC_SPECIFY( scp, A_PROTOCOL );
   SC_SPECIFY( scp, A_USER );
   SC_SPECIFY( scp, A_SOCKET_TYPE );
   SC_SPECIFY( scp, A_WAIT );

   if( ! pset_add(sconfs, scp) )
   {
      out_of_memory( func );
      pset_destroy(args);
      sc_free(scp);
      return -1;
   }

   pset_destroy(args);
   parsemsg( LOG_DEBUG, func, "added service %s", SC_NAME(scp));
   return 0;
}
Beispiel #22
0
/*
 * Print info about service scp to file descriptor fd
 */
void sc_dump( struct service_config *scp, 
              int fd, 
              int tab_level, 
              bool_int is_defaults )
{
   const struct name_value    *nvp ;
   unsigned             u ;
   char                 **pp ;

   if ( is_defaults )
      tabprint( fd, tab_level, "Service defaults\n" ) ;
   else
      tabprint( fd, tab_level, "Service configuration: %s\n", SC_NAME(scp) ) ;

   if ( ! is_defaults )
   {
      tabprint( fd, tab_level+1, "id = %s\n", SC_ID(scp) ) ;

      if ( ! M_ARE_ALL_CLEAR( SC_XFLAGS(scp) ) )
      {
         tabprint( fd, tab_level+1, "flags =" ) ;
         for ( nvp = &service_flags[ 0 ] ; nvp->name != NULL ; nvp++ )
            if ( M_IS_SET( SC_XFLAGS(scp), nvp->value ) )
               Sprint( fd, " %s", nvp->name ) ;
         Sputchar( fd, '\n' ) ;
      }

      if ( ! M_ARE_ALL_CLEAR( SC_TYPE(scp) ) )
      {
         tabprint( fd, tab_level+1, "type =" ) ;
         for ( nvp = &service_types[ 0 ] ; nvp->name != NULL ; nvp++ )
            if ( M_IS_SET( SC_TYPE(scp), nvp->value ) )
               Sprint( fd, " %s", nvp->name ) ;
         Sputchar( fd, '\n' ) ;
      }

      tabprint( fd, tab_level+1, "socket_type = %s\n",
         nv_get_name( socket_types, SC_SOCKET_TYPE(scp) ) ) ;

      tabprint( fd, tab_level+1, "Protocol (name,number) = (%s,%d)\n",
            SC_PROTONAME(scp), SC_PROTOVAL(scp) ) ;
      
      if ( SC_SPECIFIED( scp, A_PORT ) )
         tabprint( fd, tab_level+1, "port = %d\n", SC_PORT(scp) ) ;
   }

   if ( SC_SPECIFIED( scp, A_INSTANCES ) ) {
      if ( SC_INSTANCES(scp) == UNLIMITED )
         tabprint( fd, tab_level+1, "Instances = UNLIMITED\n" ) ;
      else
         tabprint( fd, tab_level+1, "Instances = %d\n", SC_INSTANCES(scp) ) ;
   }

   if ( SC_SPECIFIED( scp, A_WAIT ) ) {
      if ( SC_WAIT(scp) )
         tabprint( fd, tab_level+1, "wait = yes\n" ) ;
      else
         tabprint( fd, tab_level+1, "wait = no\n" ) ;
   }
      
   if ( SC_SPECIFIED( scp, A_USER ) )
      tabprint( fd, tab_level+1, "user = %d\n", SC_UID(scp) ) ;
      
   if ( SC_SPECIFIED( scp, A_GROUP ) )
      tabprint( fd, tab_level+1, "group = %d\n", SC_GID(scp) ) ;
      
   if ( SC_SPECIFIED( scp, A_GROUPS ) )
   {
      if (SC_GROUPS(scp) == 1)
         tabprint( fd, tab_level+1, "Groups = yes\n" );
      else
         tabprint( fd, tab_level+1, "Groups = no\n" );
   }

   if ( SC_SPECIFIED( scp, A_UMASK ) )
      tabprint( fd, tab_level+1, "umask = %o\n", SC_UMASK(scp) ) ;
      
   if ( SC_SPECIFIED( scp, A_NICE ) )
      tabprint( fd, tab_level+1, "Nice = %d\n", SC_NICE(scp) ) ;

   if ( SC_SPECIFIED( scp, A_CPS ) )
      tabprint( fd, tab_level+1, "CPS = max conn:%lu wait:%lu\n", 
         SC_TIME_CONN_MAX(scp), SC_TIME_WAIT(scp) );

   if ( SC_SPECIFIED( scp, A_PER_SOURCE ) )
      tabprint( fd, tab_level+1, "PER_SOURCE = %d\n", 
         SC_PER_SOURCE(scp) );

   if ( SC_SPECIFIED( scp, A_BIND ) ) {
	   if (  SC_BIND_ADDR(scp) ) {
		  char bindname[NI_MAXHOST];
		  unsigned int len = 0;
		  if( SC_BIND_ADDR(scp)->sa.sa_family == AF_INET ) 
			 len = sizeof(struct sockaddr_in);
		  else  
			 len = sizeof(struct sockaddr_in6);
		  memset(bindname, 0, sizeof(bindname));
		  if( getnameinfo(&SC_BIND_ADDR(scp)->sa, len, bindname, 
                                  NI_MAXHOST, NULL, 0, 0) != 0 ) 
			 strcpy(bindname, "unknown");
		  tabprint( fd, tab_level+1, "Bind = %s\n", bindname );
	   }
	   else if ( SC_ORIG_BIND_ADDR(scp) ) {
		  tabprint( fd, tab_level+1, "Bind = %s\n", 
                            SC_ORIG_BIND_ADDR(scp) );
	   }
	   else { /* This should NEVER happen */
		msg(LOG_ERR, "sc_dump", "bad configuration for %s:", 
                    SC_NAME(scp));
	   }
   }
   else
      tabprint( fd, tab_level+1, "Bind = All addresses.\n" );

   if ( ! is_defaults )
   {
      if ( (! SC_IS_INTERNAL( scp )) && (SC_REDIR_ADDR(scp) == NULL) )
      {
         tabprint( fd, tab_level+1, "Server = %s\n", SC_SERVER(scp) ) ;
         tabprint( fd, tab_level+1, "Server argv =" ) ;
	 if ( SC_SERVER_ARGV(scp) )
	 {
            for ( pp = SC_SERVER_ARGV(scp) ; *pp ; pp++ )
               Sprint( fd, " %s", *pp ) ;
	 }
	 else
	    Sprint( fd, " (NULL)");
         Sputchar( fd, '\n' ) ;
      } 

#ifdef LIBWRAP
      if ( SC_LIBWRAP(scp) != NULL )
      {
         tabprint( fd, tab_level + 1, "Libwrap = %s\n", SC_LIBWRAP(scp) );
      }
#endif

      if ( SC_REDIR_ADDR(scp) != NULL ) 
      {
         char redirname[NI_MAXHOST];
         unsigned int len = 0;
         if( SC_REDIR_ADDR(scp)->sa.sa_family == AF_INET ) 
            len = sizeof(struct sockaddr_in);
         if( SC_REDIR_ADDR(scp)->sa.sa_family == AF_INET6 ) 
            len = sizeof(struct sockaddr_in6);
         memset(redirname, 0, sizeof(redirname));
         if( getnameinfo(&SC_REDIR_ADDR(scp)->sa, len,  redirname, NI_MAXHOST, 
               NULL, 0, 0) != 0 ) 
            strcpy(redirname, "unknown");
         tabprint( fd, tab_level+1, "Redirect = %s:%d\n", redirname, 
	    SC_REDIR_ADDR(scp)->sa_in.sin_port );
      }

      if ( SC_IS_RPC( scp ) )
      {
         struct rpc_data *rdp = SC_RPCDATA( scp ) ;

         tabprint( fd, tab_level+1, "RPC data\n" ) ;
         tabprint( fd, tab_level+2,
                           "program number = %ld\n", rdp->rd_program_number ) ;
         tabprint( fd, tab_level+2, "rpc_version = " ) ;
         if ( rdp->rd_min_version == rdp->rd_max_version )
            Sprint( fd, "%ld\n", rdp->rd_min_version ) ;
         else
            Sprint( fd, "%ld-%ld\n",
                           rdp->rd_min_version, rdp->rd_max_version ) ;
      }

      if ( SC_SPECIFIED( scp, A_ACCESS_TIMES ) )
      {
         tabprint( fd, tab_level+1, "Access times =" ) ;
         ti_dump( SC_ACCESS_TIMES(scp), fd ) ;
         Sputchar ( fd, '\n' ) ;
      }
   }

   /* This is important enough that each service should list it. */
   tabprint( fd, tab_level+1, "Only from: " ) ;
   if ( SC_ONLY_FROM(scp) )
   {  /* Next check is done since -= doesn't zero out lists. */
      if ( pset_count(SC_ONLY_FROM(scp)) == 0)
         Sprint( fd, "All sites" );
      else
         addrlist_dump( SC_ONLY_FROM(scp), fd ) ;
   }
   else
      Sprint( fd, "All sites" );
   Sputchar( fd, '\n' ) ;

   /* This is important enough that each service should list it. */
   tabprint( fd, tab_level+1, "No access: " ) ;
   if ( SC_NO_ACCESS(scp) )
   {  /* Next check is done since -= doesn't zero out lists. */
      if ( pset_count(SC_NO_ACCESS(scp)) == 0)
         Sprint( fd, "No blocked sites" );
      else
         addrlist_dump( SC_NO_ACCESS(scp), fd ) ;
   }
   else
      Sprint( fd, "No blocked sites" );
   Sputchar( fd, '\n' ) ;

   if ( SC_SENSOR(scp) )
   {
      tabprint( fd, tab_level+1, "Deny Time: " ) ;
      Sprint( fd, "%d\n", SC_DENY_TIME(scp));
   }
   
   dump_log_data( fd, scp, tab_level+1 ) ;

   if ( SC_IS_PRESENT( scp, A_PASSENV ) )
   {
      tabprint( fd, tab_level+1, "Passenv =" ) ;
      for ( u = 0 ; u < pset_count( SC_PASS_ENV_VARS(scp) ) ; u++ )
         Sprint( fd, " %s",
                  (char *) pset_pointer( SC_PASS_ENV_VARS(scp), u ) ) ;
      Sputchar ( fd, '\n' ) ;
   }

   if ( ! is_defaults )
      if ( SC_SPECIFIED( scp, A_ENV ) )
      {
         tabprint( fd, tab_level+1, "Environment additions:\n" ) ;
         for ( u = 0 ; u < pset_count( SC_ENV_VAR_DEFS(scp) ) ; u++ )
            tabprint( fd, tab_level+2,
                  "%s\n", (char *) pset_pointer( SC_ENV_VAR_DEFS(scp), u ) ) ;
      }
   
   if ( SC_ENV( scp )->env_type == CUSTOM_ENV )
   {
      tabprint( fd, tab_level+1, "Environment strings:\n" ) ;
      for ( pp = env_getvars( SC_ENV( scp )->env_handle ) ; *pp ; pp++ )
         tabprint( fd, tab_level+2, "%s\n", *pp ) ;
   }
   Sflush( fd ) ;
}
Beispiel #23
0
void dump_internal_state(void)
{
   int dump_fd ;
   const char *dump_file = DUMP_FILE ;
   time_t current_time ;
   int fd ;
   unsigned u ;
   const char *func = "dump_internal_state" ;

   if ( debug.on )
      msg( LOG_DEBUG, func, "Dumping State" ) ;

   dump_fd = open( dump_file, O_WRONLY | O_CREAT | O_APPEND, DUMP_FILE_MODE);
   if ( dump_fd == -1 )
   {
      msg( LOG_ERR, func, "failed to open %s: %m", dump_file ) ;
      return ;
   }
   
   if (Sbuftype( dump_fd, SIO_LINEBUF ) == SIO_ERR )
   {
       /*
	* If the above function failed, Sprint will most likely
	* fail, too. Output a message for troubleshooting and quit.
	*/
       msg( LOG_ERR, func, "failed setting up sio buffering: %m" ) ;
       return;
   }

   /*
    * Print the program name, version, and timestamp.
    * Note that the program_version variable contains the program name.
    */
   (void) time( &current_time ) ;
   Sprint( dump_fd, "INTERNAL STATE DUMP: %s\n", program_version ) ;
   Sprint( dump_fd, "Current time: %s\n", ctime( &current_time ) ) ;

   dump_services( dump_fd ) ;

   /*
    * Dump the server table
    */
   Sprint( dump_fd, "Server table dump:\n" ) ;
   for ( u = 0 ; u < pset_count( SERVERS( ps ) ) ; u++ )
      server_dump( SERP( pset_pointer( SERVERS( ps ), u ) ), dump_fd ) ;
   Sputchar( dump_fd, '\n' ) ;

   /*
    * Dump the retry_table
    */
   Sprint( dump_fd, "Retry table dump:\n" ) ;
   for ( u = 0 ; u < pset_count( RETRIES( ps ) ) ; u++ )
      server_dump( SERP( pset_pointer( RETRIES( ps ), u ) ), dump_fd ) ;
   Sputchar( dump_fd, '\n' ) ;

   /*
    * Dump the socket mask
    */
   Sprint( dump_fd, "Socket mask:" ) ;
   for ( fd = 0 ; fd < ps.ros.max_descriptors ; fd++ )
      if ( FD_ISSET( fd, &ps.rws.socket_mask ) )
         Sprint( dump_fd, " %d", fd ) ;
   Sputchar( dump_fd, '\n' ) ;
   Sprint( dump_fd, "mask_max = %d\n", ps.rws.mask_max ) ;

   /*
    * Dump the descriptors that are open and are *not* in the socket mask
    */
   Sprint( dump_fd, "Open descriptors (not in socket mask):" ) ;
   for ( fd = 0 ; fd < ps.ros.max_descriptors ; fd++ )
   {
      struct stat st ;

      if ( FD_ISSET( fd, &ps.rws.socket_mask ) )
         continue ;
      if ( fstat( fd, &st ) == -1 )
         continue ;
      Sprint( dump_fd, " %d", fd ) ;
   }
   Sputchar( dump_fd, '\n' ) ;
   Sputchar( dump_fd, '\n' ) ;

   Sprint( dump_fd, "active_services = %d\n", ps.rws.active_services ) ;
   Sprint( dump_fd, "available_services = %d\n", ps.rws.available_services ) ;
   Sprint( dump_fd, "descriptors_free = %d\n", ps.rws.descriptors_free ) ;
   Sprint( dump_fd, "running_servers = %d\n", pset_count( SERVERS( ps ) ) ) ;
   Sprint( dump_fd, "Logging service = %s\n",
            LOG_SERVICE( ps ) != NULL ? "enabled" : "not enabled" ) ;
   Sputchar( dump_fd, '\n' ) ;

   Sprint( dump_fd, "max_descriptors = %d\n", (int)ps.ros.max_descriptors ) ;
   Sprint( dump_fd, "process_limit = %d\n", (int)ps.ros.process_limit ) ;
   Sprint( dump_fd, "config_file = %s\n", ps.ros.config_file ) ;
   if ( debug.on )
      Sprint( dump_fd, "debug_fd = %d\n", debug.fd ) ;
   Sputchar( dump_fd, '\n' ) ;

   Sprint( dump_fd, "END OF DUMP\n\n" ) ;
   Sclose( dump_fd );

   msg( LOG_INFO, func, "generated state dump in file %s", dump_file ) ;
}
Beispiel #24
0
/*
 * Identify the attribute in <attr_name>.
 *
 * Check if
 *      1) the attribute has been defined already
 *      2) the value count is correct
 *      3) the assign op is appropriate
 *
 * Invoke appropriate parser.
 *
 * This function will return FAILED only if its in the default section
 * and an attribute cannot be ID'd. Otherwise, it returns OK.
 */
static status_e identify_attribute( entry_e entry_type,
                                    struct service_config *scp,
                                    const char *attr_name,
                                    enum assign_op op,
                                    pset_h attr_values )
{
    const struct attribute   *ap ;
    const char         *func = "identify_attribute" ;

    if ( entry_type == SERVICE_ENTRY )
        ap = attr_lookup( service_attributes, attr_name ) ;
    else
        ap = attr_lookup( default_attributes, attr_name ) ;

    if ( ap == NULL )
        return OK;   /* We simply ignore keywords not on the list */

    if ( ! MODIFIABLE( ap ) )
    {
        if ( SC_SPECIFIED( scp, ap->a_id ) )
        {
            parsemsg( LOG_WARNING, func, "Service %s: attribute already set: %s",
                      SC_NAME(scp), attr_name ) ;
            return OK;
        }

        if ( op != SET_EQ )
        {
            parsemsg( LOG_WARNING, func,
                      "Service %s: operator '%s' cannot be used for attribute '%s'",
                      SC_NAME(scp), ( op == PLUS_EQ ) ? "+=" : "-=", attr_name ) ;
            return OK;
        }
    }
    else      /* modifiable attribute */
    {
        /*
         * For the defaults entry, '=' and '+=' have the same meaning
         */
        if ( entry_type == DEFAULTS_ENTRY && op == SET_EQ )
            op = PLUS_EQ ;
    }

    if ( FIXED_VALUES( ap ) &&
            (unsigned)ap->a_nvalues != pset_count( attr_values ) )
    {
        parsemsg( LOG_WARNING, func,
                  "attribute %s expects %d values and %d values were specified",
                  attr_name, ap->a_nvalues, pset_count( attr_values ) ) ;
        return OK;
    }

    if ( (*ap->a_parser)( attr_values, scp, op ) == OK )
    {   /* This is the normal path. */
        SC_SPECIFY( scp, ap->a_id ) ;
    }
    else if ( entry_type == SERVICE_ENTRY )
    {
        parsemsg( LOG_ERR, func,
                  "Error parsing attribute %s - DISABLING SERVICE", attr_name ) ;
        SC_DISABLE( scp );
    }
    /*
     * We are in the default section and an error was detected. At
     * this point, we should terminate since whatever attribute
     * was trying to be specified cannot be propagated.
     */
    else if ( !debug.on )
        return FAILED;

    return OK;
}