~noskcaj/ubuntu/saucy/xinetd/2.3.15

« back to all changes in this revision

Viewing changes to xinetd/intcommon.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Seyrat
  • Date: 2004-04-18 13:33:57 UTC
  • Revision ID: james.westby@ubuntu.com-20040418133357-czeqeju37433xvdd
Tags: upstream-2.3.13
ImportĀ upstreamĀ versionĀ 2.3.13

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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.
 
6
 */
 
7
 
 
8
#include "config.h"
 
9
#include <sys/types.h>
 
10
#include <sys/time.h>
 
11
#include <sys/socket.h>
 
12
#include <signal.h>
 
13
#include <syslog.h>
 
14
#include <errno.h>
 
15
#include <stdlib.h>
 
16
#include <unistd.h>
 
17
 
 
18
#include "intcommon.h"
 
19
#include "msg.h"
 
20
#include "signals.h"
 
21
#include "connection.h"
 
22
#include "sconf.h"
 
23
#include "state.h"
 
24
#include "main.h"
 
25
#include "xconfig.h"
 
26
 
 
27
 
 
28
void int_fail( const struct intercept_s *ip, const char *lsyscall )
 
29
{
 
30
   msg( LOG_ERR, "fail", "%s failed: %m", lsyscall ) ;
 
31
   (*ip->int_ops->exit)() ;
 
32
   /* NOTREACHED */
 
33
}
 
34
 
 
35
 
 
36
/*
 
37
 * Returns either a positive number or -1
 
38
 */
 
39
int int_select( int max, fd_set *read_mask )
 
40
{
 
41
   const char *func = "int_select" ;
 
42
 
 
43
   for ( ;; )
 
44
   {
 
45
      int n_ready ;
 
46
 
 
47
      n_ready = select( max+1, read_mask,
 
48
                                 FD_SET_NULL, FD_SET_NULL, TIMEVAL_NULL ) ;
 
49
      if ( n_ready > 0 )
 
50
         return( n_ready ) ;
 
51
      else if ( n_ready == -1 ) {
 
52
         if ( errno == EINTR )
 
53
            continue ;
 
54
         else
 
55
         {
 
56
            msg( LOG_ERR, func, "select: %m" ) ;
 
57
            return( -1 ) ;
 
58
         }
 
59
      }
 
60
   }
 
61
}
 
62
 
 
63
 
 
64
void int_exit( struct intercept_s *ip )
 
65
{
 
66
   int status = SERVER_EXITSTATUS( INT_SERVER( ip ) ) ;
 
67
   const char *func = "int_exit" ;
 
68
 
 
69
   if ( debug.on )
 
70
   {
 
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 ) ) ) ;
 
76
   }
 
77
   _exit( (int) PROC_EXITSTATUS( status ) ) ;
 
78
}
 
79
 
 
80
 
 
81
/*
 
82
 * The ops vector must be installed before invoking this function
 
83
 */
 
84
void int_init( struct intercept_s *ip, struct server *serp )
 
85
{
 
86
   unsigned u ;
 
87
   const char *func = "int_init" ;
 
88
 
 
89
   /*
 
90
    * Sanity test
 
91
    */
 
92
   if ( SERVER_SERVICE( serp ) != SERVER_CONNSERVICE( serp ) )
 
93
   {
 
94
      msg( LOG_ERR, func, "server service (%s) != connection service (%s)",
 
95
                           SVC_ID( SERVER_SERVICE( serp ) ),
 
96
                              SVC_ID( SERVER_CONNSERVICE( serp ) ) ) ;
 
97
      exit( 1 ) ;
 
98
   }
 
99
 
 
100
   /*
 
101
    * Close all unneeded descriptors
 
102
    */
 
103
   for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
 
104
   {
 
105
      struct service *sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
 
106
 
 
107
      if ( sp == SERVER_SERVICE( serp ) )
 
108
         continue ;
 
109
      if ( LOG_GET_TYPE( SC_LOG( SVC_CONF( sp ) ) ) == L_FILE )
 
110
         xlog_destroy( SVC_LOG( sp ) ) ;
 
111
      (void) Sclose( SVC_FD( sp ) ) ;
 
112
   }
 
113
 
 
114
   /*
 
115
    * Setup signal handling
 
116
    */
 
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" ) ;
 
123
   
 
124
   /*
 
125
    * Initialize state
 
126
    */
 
127
   INTERCEPT( ip ) = TRUE ;
 
128
   *INT_SERVER( ip ) = *serp ;
 
129
   INT_REMOTE( ip ) = SERVER_FD( serp ) ;
 
130
 
 
131
   INT_CONNECTIONS( ip ) = pset_create( 0, 0 ) ;
 
132
   if ( INT_CONNECTIONS( ip ) == NULL )
 
133
   {
 
134
      msg( LOG_ERR, func, ES_NOMEM ) ;
 
135
      (*ip->int_ops->exit)() ;
 
136
   }
 
137
}
 
138
 
 
139
 
 
140
/*
 
141
 * Make a new connection to the local server
 
142
 */
 
143
channel_s *int_newconn( struct intercept_s *ip, 
 
144
                        union xsockaddr *sinp,
 
145
                        int remote_socket )
 
146
{
 
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 ) ;
 
151
   channel_s            *chp ;
 
152
   int                   sd ;
 
153
   const char           *func = "int_newconn" ;
 
154
 
 
155
   /*
 
156
    * Get a socket and connect it to the local address
 
157
    *
 
158
    */
 
159
   if ( ( sd = socket( local->sa.sa_family, socket_type, SC_PROTOVAL(SVC_CONF(sp)) ) ) == -1 )
 
160
   {
 
161
      msg( LOG_ERR, func,"(intercepting %s) socket creation failed: %m", sid ) ;
 
162
      return( CHANNEL_NULL ) ;
 
163
   }
 
164
 
 
165
   if ( connect( sd, SA( local ), sizeof( *local ) ) == -1 )
 
166
   {
 
167
      msg( LOG_ERR, func, "(intercepting %s) connect failed: %m", sid ) ;
 
168
      (void) Sclose( sd ) ;
 
169
      return( CHANNEL_NULL ) ;
 
170
   }
 
171
 
 
172
   chp = NEW_CHANNEL() ;
 
173
   if ( chp == CHANNEL_NULL )
 
174
   {
 
175
      msg( LOG_ERR, func, ES_NOMEM ) ;
 
176
      (void) Sclose( sd ) ;
 
177
      return( CHANNEL_NULL ) ;
 
178
   }
 
179
 
 
180
   if ( pset_add( INT_CONNECTIONS( ip ), chp ) == NULL )
 
181
   {
 
182
      msg( LOG_ERR, func, ES_NOMEM ) ;
 
183
      FREE_CHANNEL( chp ) ;
 
184
      (void) Sclose( sd ) ;
 
185
      return( CHANNEL_NULL ) ;
 
186
   }
 
187
 
 
188
   chp->ch_state = GOOD_CHANNEL ;
 
189
   chp->ch_from = *sinp ;
 
190
   chp->ch_local_socket = sd ;
 
191
   chp->ch_remote_socket = remote_socket ;
 
192
   return( chp ) ;
 
193
}
 
194
 
 
195
 
 
196
 
 
197
/*
 
198
 * Check if the (address,port) in sinp is already in the connection table.
 
199
 * Return value:
 
200
 *    a connection pointer if the address is found
 
201
 *    NULL if the address if not found
 
202
 *
 
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.
 
205
 */
 
206
channel_s *int_lookupconn( struct intercept_s *ip, 
 
207
                           union xsockaddr *sinp,
 
208
                           bool_int *addr_checked )
 
209
{
 
210
   unsigned      u ;
 
211
   pset_h      conntab = INT_CONNECTIONS( ip ) ;
 
212
 
 
213
   *addr_checked = FALSE ;
 
214
 
 
215
   for ( u = 0 ; u < pset_count( conntab ) ; u++ )
 
216
   {
 
217
      register channel_s *chp = CHP( pset_pointer( conntab, u ) ) ;
 
218
 
 
219
      if ( memcmp( &chp->ch_from, sinp, sizeof( *sinp ) ) == 0 )
 
220
      {
 
221
         *addr_checked = TRUE ;
 
222
         if ( xaddrport(&chp->ch_from) == xaddrport(sinp) )
 
223
            return( chp ) ;
 
224
      }
 
225
   }
 
226
   return( CHANNEL_NULL ) ;
 
227
}