2 * (c) Copyright 1992 by Panagiotis Tsirigotis
3 * (c) Sections Copyright 1998-2001 by Rob Braun
4 * All rights reserved. The file named COPYRIGHT specifies the terms
5 * and conditions for redistribution.
11 #include <sys/socket.h>
18 #include "intcommon.h"
21 #include "connection.h"
28 void int_fail( const struct intercept_s *ip, const char *lsyscall )
30 msg( LOG_ERR, "fail", "%s failed: %m", lsyscall ) ;
31 (*ip->int_ops->exit)() ;
37 * Returns either a positive number or -1
39 int int_select( int max, fd_set *read_mask )
41 const char *func = "int_select" ;
47 n_ready = select( max+1, read_mask,
48 FD_SET_NULL, FD_SET_NULL, TIMEVAL_NULL ) ;
51 else if ( n_ready == -1 ) {
56 msg( LOG_ERR, func, "select: %m" ) ;
64 void int_exit( struct intercept_s *ip )
66 int status = SERVER_EXITSTATUS( INT_SERVER( ip ) ) ;
67 const char *func = "int_exit" ;
71 if ( PROC_EXITED( status ) )
72 msg( LOG_DEBUG, func, "intercepted server died" ) ;
73 else if ( PROC_SIGNALED( status ) )
74 msg( LOG_DEBUG, func, "intercepted server received signal %s",
75 sig_name( (int) PROC_TERMSIG( status ) ) ) ;
77 _exit( (int) PROC_EXITSTATUS( status ) ) ;
82 * The ops vector must be installed before invoking this function
84 void int_init( struct intercept_s *ip, struct server *serp )
87 const char *func = "int_init" ;
92 if ( SERVER_SERVICE( serp ) != SERVER_CONNSERVICE( serp ) )
94 msg( LOG_ERR, func, "server service (%s) != connection service (%s)",
95 SVC_ID( SERVER_SERVICE( serp ) ),
96 SVC_ID( SERVER_CONNSERVICE( serp ) ) ) ;
101 * Close all unneeded descriptors
103 for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
105 struct service *sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
107 if ( sp == SERVER_SERVICE( serp ) )
109 if ( LOG_GET_TYPE( SC_LOG( SVC_CONF( sp ) ) ) == L_FILE )
110 xlog_destroy( SVC_LOG( sp ) ) ;
111 (void) Sclose( SVC_FD( sp ) ) ;
115 * Setup signal handling
117 if ( signal( SERVER_EXIT_SIG, int_sighandler ) == SIG_ERR )
118 int_fail( ip, "signal" ) ;
119 if ( signal( INTERCEPT_SIG, int_sighandler ) == SIG_ERR )
120 int_fail( ip, "signal" ) ;
121 if ( signal( SIGTERM, int_sighandler ) == SIG_ERR )
122 int_fail( ip, "signal" ) ;
127 INTERCEPT( ip ) = TRUE ;
128 *INT_SERVER( ip ) = *serp ;
129 INT_REMOTE( ip ) = SERVER_FD( serp ) ;
131 INT_CONNECTIONS( ip ) = pset_create( 0, 0 ) ;
132 if ( INT_CONNECTIONS( ip ) == NULL )
134 msg( LOG_ERR, func, ES_NOMEM ) ;
135 (*ip->int_ops->exit)() ;
141 * Make a new connection to the local server
143 channel_s *int_newconn( struct intercept_s *ip,
144 union xsockaddr *sinp,
147 struct service *sp = SERVER_SERVICE( INT_SERVER( ip ) ) ;
148 int socket_type = SVC_SOCKET_TYPE( sp ) ;
149 union xsockaddr *local = INT_LOCALADDR( ip ) ;
150 char *sid = SVC_ID( sp ) ;
153 const char *func = "int_newconn" ;
156 * Get a socket and connect it to the local address
159 if ( ( sd = socket( local->sa.sa_family, socket_type, SC_PROTOVAL(SVC_CONF(sp)) ) ) == -1 )
161 msg( LOG_ERR, func,"(intercepting %s) socket creation failed: %m", sid ) ;
162 return( CHANNEL_NULL ) ;
165 if ( connect( sd, SA( local ), sizeof( *local ) ) == -1 )
167 msg( LOG_ERR, func, "(intercepting %s) connect failed: %m", sid ) ;
168 (void) Sclose( sd ) ;
169 return( CHANNEL_NULL ) ;
172 chp = NEW_CHANNEL() ;
173 if ( chp == CHANNEL_NULL )
175 msg( LOG_ERR, func, ES_NOMEM ) ;
176 (void) Sclose( sd ) ;
177 return( CHANNEL_NULL ) ;
180 if ( pset_add( INT_CONNECTIONS( ip ), chp ) == NULL )
182 msg( LOG_ERR, func, ES_NOMEM ) ;
183 FREE_CHANNEL( chp ) ;
184 (void) Sclose( sd ) ;
185 return( CHANNEL_NULL ) ;
188 chp->ch_state = GOOD_CHANNEL ;
189 chp->ch_from = *sinp ;
190 chp->ch_local_socket = sd ;
191 chp->ch_remote_socket = remote_socket ;
198 * Check if the (address,port) in sinp is already in the connection table.
200 * a connection pointer if the address is found
201 * NULL if the address if not found
203 * *addr_checked is set to TRUE of FALSE depending on whether there
204 * is already a connection from the same IP address in the table.
206 channel_s *int_lookupconn( struct intercept_s *ip,
207 union xsockaddr *sinp,
208 bool_int *addr_checked )
211 pset_h conntab = INT_CONNECTIONS( ip ) ;
213 *addr_checked = FALSE ;
215 for ( u = 0 ; u < pset_count( conntab ) ; u++ )
217 register channel_s *chp = CHP( pset_pointer( conntab, u ) ) ;
219 if ( memcmp( &chp->ch_from, sinp, sizeof( *sinp ) ) == 0 )
221 *addr_checked = TRUE ;
222 if ( xaddrport(&chp->ch_from) == xaddrport(sinp) )
226 return( CHANNEL_NULL ) ;