home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / xinetd / xinetd.2.0.6 / int.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-22  |  4.8 KB  |  239 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: int.c,v 5.2 1992/11/03 00:57:56 panos Exp $" ;
  8.  
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <syslog.h>
  12. #include <errno.h>
  13. #include <signal.h>
  14.  
  15. #include "defs.h"
  16. #include "int.h"
  17. #include "server.h"
  18. #include "config.h"
  19.  
  20. void msg() ;
  21. char *inet_ntoa() ;
  22. unsigned long inet_addr() ;
  23.  
  24. typedef struct intercept *(*initfunc)() ;
  25.  
  26. struct lookup_table
  27. {
  28.     initfunc initializer ;
  29.     int socket_type ;
  30. } ;
  31.  
  32. extern struct intercept *di_init() ;
  33. extern struct intercept *si_init() ;
  34.  
  35. static struct lookup_table intercept_lookup_table[] =
  36.     {
  37.         { di_init,            SOCK_DGRAM },
  38.         { si_init,            SOCK_STREAM },
  39.         { NULL }
  40.     } ;
  41.  
  42.             
  43. /*
  44.  * This variable has file scope for the benefit of the signal handler
  45.  */
  46. static struct intercept *intp ;
  47.  
  48.  
  49. /*
  50.  * This function is the interface of the intercept code with the rest of 
  51.  * the program. 
  52.  */
  53. void intercept( serp )
  54.     struct server *serp ;
  55. {
  56.     struct service_config *scp = CONF( SERVER_SERVICE( serp ) ) ;
  57.     initfunc initializer ;
  58.     initfunc find_initializer() ;
  59.     void start_server() ;
  60.     void terminate_server() ;
  61.  
  62. #ifdef DEBUG_INTERCEPTOR
  63.     if ( debug.on )
  64.     {
  65.         msg( LOG_DEBUG, "intercept", "%d is sleeping", getpid() ) ;
  66.         sleep( 10 ) ;
  67.     }
  68. #endif
  69.  
  70.     initializer = find_initializer( scp->socket_type ) ;
  71.     intp = (*initializer)( serp ) ;
  72.     start_server( intp ) ;
  73.     (*intp->ops->mux)() ;
  74.     terminate_server( intp ) ;
  75.     /*
  76.      * the terminate_server function should not return but even if it
  77.      * does, child_process will do the _exit.
  78.      */ 
  79. }
  80.  
  81.  
  82.  
  83. PRIVATE initfunc find_initializer( type )
  84.     int type ;
  85. {
  86.     struct lookup_table *ltp ;
  87.  
  88.     for ( ltp = intercept_lookup_table ; ltp->initializer ; ltp++ )
  89.         if ( ltp->socket_type == type )
  90.             return( ltp->initializer ) ;
  91.     msg( LOG_ERR, "find_initializer", "No initializer for type %d", type ) ;
  92.     _exit( 0 ) ;
  93.     /* NOTREACHED */
  94. }
  95.  
  96.  
  97.  
  98. PRIVATE void start_server( ip )
  99.     struct intercept *ip ;
  100. {
  101.     struct service *sp = INT_SERVER( ip )->sp ;
  102.     int server_socket ;
  103.     pid_t pid ;
  104.     void child_process() ;
  105.  
  106.     server_socket = get_server_socket( ip ) ;
  107.     
  108.     pid = fork() ;
  109.     if ( pid == -1 )
  110.         int_fail( ip, "fork" ) ;
  111.     
  112.     if ( pid == 0 )
  113.     {
  114.         SERVER_FD( INT_SERVER( ip ) ) = server_socket ;
  115.         M_CLEAR( CONF( sp )->type, ST_INTERNAL ) ;   /* avoid looping */
  116.         child_process( INT_SERVER( ip ) ) ;
  117.         /* NOTREACHED */
  118.     }
  119.     INT_SERVER( ip )->pid = pid ;
  120.     (void) close( server_socket ) ;
  121. }
  122.  
  123.  
  124. /*
  125.  * Create a socket and bind it to (INADDR_LOOPBACK,0)
  126.  */
  127. PRIVATE int get_server_socket( ip )
  128.     struct intercept *ip ;
  129. {
  130.     struct service_config *scp = CONF( INT_SERVER( ip )->sp ) ;
  131.     struct sockaddr_in *sinp = INT_LOCALADDR( ip ) ;
  132.     int sd ;
  133.     int size ;
  134.     char *func = "get_server_socket" ;
  135.  
  136.     if ( ( sd = socket( AF_INET, scp->socket_type, 0 ) ) == -1 )
  137.         int_fail( ip, "socket creation" ) ;
  138.     
  139.     sinp->sin_family = AF_INET ;
  140. #ifdef INADDR_LOOPBACK
  141.     sinp->sin_addr.s_addr = htonl( INADDR_LOOPBACK ) ;
  142. #else
  143.     sinp->sin_addr.s_addr = inet_addr( "127.0.0.1" ) ;
  144. #endif
  145.     sinp->sin_port = 0 ;
  146.  
  147.     if ( bind( sd, SA( sinp ), sizeof( *sinp ) ) == -1 )
  148.         int_fail( ip, "bind" ) ;
  149.     
  150.     size = sizeof( *sinp ) ;
  151.     if ( getsockname( sd, SA( sinp ), &size ) == -1 )
  152.         int_fail( ip, "getsockname" ) ;
  153.     
  154.     if ( debug.on )
  155.         msg( LOG_DEBUG, func, "address = %s, port = %d",
  156.             inet_ntoa( sinp->sin_addr ), ntohs( sinp->sin_port ) ) ;
  157.         
  158.     if ( ip->socket_type == SOCK_STREAM )
  159.         (void) listen( sd, LISTEN_BACKLOG ) ;
  160.     
  161.     return( sd ) ;
  162. }
  163.  
  164.  
  165. void int_sighandler( sig )
  166.     int sig ;
  167. {
  168.     char *func = "int_sighandler" ;
  169.     status_e wait_child() ;
  170.     void terminate_server() ;
  171.  
  172.     if ( debug.on )
  173.         msg( LOG_DEBUG, func, "Received signal %d", sig ) ;
  174.  
  175.     if ( sig == SERVER_EXIT_SIG )
  176.     {
  177.         if ( wait_child( intp ) == OK )
  178.             (*intp->ops->exit)() ;
  179.     }
  180.     else if ( sig == INTERCEPT_SIG )
  181.         INTERCEPT( intp ) = FALSE ;
  182.     else if ( sig == SIGTERM )
  183.         terminate_server( intp ) ;
  184. }
  185.  
  186.  
  187. PRIVATE void terminate_server( ip )
  188.     struct intercept *ip ;
  189. {
  190.     (void) kill( INT_SERVER( intp )->pid, SIGKILL ) ;
  191.     /*
  192.      * Normally, wait_child should never return since a SIGCHLD will 
  193.      * invoke the signal handler which will then call the exit function.
  194.      */
  195.     if ( wait_child( ip ) == OK )
  196.         (*intp->ops->exit)() ;
  197. }
  198.  
  199.  
  200. /*
  201.  * Return value:
  202.  *            OK             if the server died
  203.  *            FAILED         otherwise
  204.  */
  205. PRIVATE status_e wait_child( ip )
  206.     struct intercept *ip ;
  207. {
  208.     char *func = "wait_child" ;
  209.  
  210.     for ( ;; )
  211.     {
  212.         int status ;
  213.         pid_t pid = wait( &status ) ;
  214.  
  215.         if ( pid == -1 )
  216.         {
  217.             if ( errno != EINTR )
  218.             {
  219.                 msg( LOG_ERR, func, "wait: %m" ) ;
  220.                 return( FAILED ) ;
  221.             }
  222.         }
  223.         else if ( pid == INT_SERVER( ip )->pid )
  224.         {
  225.             if ( PROC_STOPPED( status ) )
  226.                 return( FAILED ) ;
  227.             INT_SERVER( ip )->exit_status = status ;
  228.             return( OK ) ;
  229.         }
  230.         else
  231.         {
  232.             msg( LOG_ERR, func,
  233.                 "wait returned pid of unknown process: %d", pid ) ;
  234.             return( FAILED ) ;
  235.         }
  236.     }
  237. }
  238.  
  239.