~noskcaj/ubuntu/saucy/xinetd/2.3.15

« back to all changes in this revision

Viewing changes to xinetd/builtins.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
 
 
9
#include "config.h"
 
10
#include <sys/types.h>
 
11
#include <sys/socket.h>
 
12
#include <netinet/in.h>
 
13
#include <arpa/inet.h>
 
14
#include <errno.h>
 
15
#include <time.h>
 
16
#include <syslog.h>
 
17
#include <stdlib.h>
 
18
#include <unistd.h>
 
19
#ifdef HAVE_NETDB_H
 
20
#include <netdb.h>
 
21
#endif
 
22
 
 
23
#include "str.h"
 
24
#include "pset.h"
 
25
#include "sio.h"
 
26
#include "builtins.h"
 
27
#include "msg.h"
 
28
#include "connection.h"
 
29
#include "server.h"
 
30
#include "service.h"
 
31
#include "sconf.h"
 
32
#include "main.h"
 
33
#include "util.h"
 
34
#include "xconfig.h"
 
35
#include "state.h"
 
36
#include "libportable.h"
 
37
#include "signals.h"
 
38
#include "nvlists.h"
 
39
#include "child.h"
 
40
#include "access.h"
 
41
 
 
42
#define BUFFER_SIZE               1024
 
43
 
 
44
static void stream_echo(const struct server *) ;
 
45
static void dgram_echo(const struct server *) ;
 
46
static void stream_discard(const struct server *) ;
 
47
static void dgram_discard(const struct server *) ;
 
48
static void stream_time(const struct server *) ;
 
49
static void dgram_time(const struct server *) ;
 
50
static void stream_daytime(const struct server *) ;
 
51
static void dgram_daytime(const struct server *) ;
 
52
static void stream_chargen(const struct server *) ;
 
53
static void dgram_chargen(const struct server *) ;
 
54
static void tcpmux_handler(const struct server *) ;
 
55
static int bad_port_check(const union xsockaddr *, const char *);
 
56
 
 
57
/*
 
58
 * SG - This is the call sequence to get to a built-in service
 
59
 *
 
60
 *   main_loop                  main.c
 
61
 *    svc_request                  service.c
 
62
 *     svc_handle -- aka svc_handler_func -- aka svc_generic_handler   service.c
 
63
 *      server_run                      server.c
 
64
 *       server_internal               server.c
 
65
 *      SC_INTERNAL               service.h
 
66
 *       BUILTIN_INVOKE               sc_conf.h
 
67
 *        sc_builtin -- index into builtin_services   builtins.c
 
68
 */
 
69
 
 
70
static const struct builtin_service builtin_services[] =
 
71
   {
 
72
      { "echo",      SOCK_STREAM,   { stream_echo,     FORK    } },
 
73
      { "echo",      SOCK_DGRAM,    { dgram_echo,      NO_FORK } },
 
74
      { "discard",   SOCK_STREAM,   { stream_discard,  FORK    } },
 
75
      { "discard",   SOCK_DGRAM,    { dgram_discard,   NO_FORK } },
 
76
      { "time",      SOCK_STREAM,   { stream_time,     NO_FORK } },
 
77
      { "time",      SOCK_DGRAM,    { dgram_time,      NO_FORK } },
 
78
      { "daytime",   SOCK_STREAM,   { stream_daytime,  NO_FORK } },
 
79
      { "daytime",   SOCK_DGRAM,    { dgram_daytime,   NO_FORK } },
 
80
      { "chargen",   SOCK_STREAM,   { stream_chargen,  FORK    } },
 
81
      { "chargen",   SOCK_DGRAM,    { dgram_chargen,   NO_FORK } },
 
82
      { "sensor",    SOCK_STREAM,   { stream_discard,  NO_FORK } },
 
83
      { "sensor",    SOCK_DGRAM,    { dgram_discard,   NO_FORK } },
 
84
      { "tcpmux",    SOCK_STREAM,   { tcpmux_handler,  FORK    } },
 
85
      { NULL,        0,             { NULL,            0       } }
 
86
   } ;
 
87
 
 
88
 
 
89
const builtin_s *builtin_find( const char *service_name, int type )
 
90
{
 
91
   const builtin_s   *bsp ;
 
92
   const char        *func = "builtin_find" ;
 
93
   
 
94
   if ( (bsp = builtin_lookup( builtin_services, service_name, type )) )
 
95
      return( bsp ) ;
 
96
   else
 
97
   {
 
98
        const char *type_name;
 
99
        const struct name_value *sock_type = nv_find_name( socket_types, type );
 
100
        if (sock_type == NULL)
 
101
                type_name = "Unknown socket type";
 
102
        else
 
103
                type_name = sock_type->name;
 
104
        msg( LOG_ERR, func, "No such internal service: %s/%s - DISABLING", 
 
105
                        service_name, type_name ) ;
 
106
        return( NULL ) ;
 
107
   }
 
108
}
 
109
 
 
110
 
 
111
const builtin_s *builtin_lookup( const struct builtin_service services[], 
 
112
                           const char *service_name, 
 
113
                           int type )
 
114
{
 
115
   const struct builtin_service *bsp ;
 
116
   
 
117
   for ( bsp = services ; bsp->bs_name != NULL ; bsp++ )
 
118
      if ( EQ( bsp->bs_name, service_name ) && bsp->bs_socket_type == type )
 
119
         return( &bsp->bs_handle ) ;
 
120
   return( NULL ) ;
 
121
}
 
122
 
 
123
 
 
124
/*
 
125
 * The rest of this file contains the functions that implement the 
 
126
 * builtin services
 
127
 */
 
128
 
 
129
 
 
130
static void stream_echo( const struct server *serp )
 
131
{
 
132
   char   buf[ BUFFER_SIZE ] ;
 
133
   int    cc ;
 
134
   int    descriptor = SERVER_FD( serp ) ;
 
135
   struct service *svc = SERVER_SERVICE( serp ) ;;
 
136
 
 
137
   if( SVC_WAITS( svc ) ) {
 
138
      descriptor = accept(descriptor, NULL, NULL);
 
139
      if ( descriptor == -1 ) {
 
140
         if ((errno == EMFILE) || (errno == ENFILE))
 
141
            cps_service_stop(svc, "no available descriptors");
 
142
         return;
 
143
      }
 
144
   }
 
145
 
 
146
   close_all_svc_descriptors();
 
147
 
 
148
   for ( ;; )
 
149
   {
 
150
      cc = read( descriptor, buf, sizeof( buf ) ) ;
 
151
      if ( cc == 0 )
 
152
         break ;
 
153
      if ( cc == -1 ) {
 
154
         if ( errno == EINTR )
 
155
            continue ;
 
156
         else
 
157
            break ;
 
158
      }
 
159
 
 
160
      if ( write_buf( descriptor, buf, cc ) == FAILED )
 
161
         break ;
 
162
   }
 
163
   if( SVC_WAITS( svc ) ) /* Service forks, so close it */
 
164
      Sclose(descriptor);
 
165
}
 
166
 
 
167
/* For internal UDP services, make sure we don't respond to our ports
 
168
 * on other servers and to low ports of other services (such as DNS).
 
169
 * This can cause looping.
 
170
 */
 
171
static int bad_port_check( const union xsockaddr *sa, const char *func )
 
172
{
 
173
   uint16_t port = 0;
 
174
 
 
175
   port = ntohs( xaddrport( sa ) );
 
176
 
 
177
   if ( port < 1024 ) {
 
178
      msg(LOG_WARNING, func,
 
179
         "Possible Denial of Service attack from %s %d", xaddrname(sa), port);
 
180
      return (-1);
 
181
   }
 
182
 
 
183
   return (0);
 
184
}
 
185
 
 
186
static void dgram_echo( const struct server *serp )
 
187
{
 
188
   char            buf[ DATAGRAM_SIZE ] ;
 
189
   union xsockaddr lsin;
 
190
   int             cc ;
 
191
   unsigned int    sin_len = 0;
 
192
   int             descriptor = SERVER_FD( serp ) ;
 
193
   const char     *func = "dgram_echo";
 
194
 
 
195
   if( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
 
196
      sin_len = sizeof( struct sockaddr_in );
 
197
   else if( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
 
198
      sin_len = sizeof( struct sockaddr_in6 );
 
199
 
 
200
   cc = recvfrom( descriptor, buf, sizeof( buf ), 0, SA( &lsin ), &sin_len ) ;
 
201
   if ( cc != -1 ) {
 
202
      if( bad_port_check(&lsin, func) != 0 ) return;
 
203
      (void) sendto( descriptor, buf, cc, 0, SA( &lsin ), sizeof( lsin ) ) ;
 
204
   }
 
205
}
 
206
 
 
207
static void stream_discard( const struct server *serp )
 
208
{
 
209
   char  buf[ BUFFER_SIZE ] ;
 
210
   int   cc ;
 
211
   int    descriptor = SERVER_FD( serp ) ;
 
212
   struct service *svc = SERVER_SERVICE( serp ) ;;
 
213
 
 
214
   if( SVC_WAITS( svc ) ) {
 
215
      descriptor = accept(descriptor, NULL, NULL);
 
216
      if ( descriptor == -1 ) {
 
217
         if ((errno == EMFILE) || (errno == ENFILE))
 
218
            cps_service_stop(svc, "no available descriptors");
 
219
         return;
 
220
      }
 
221
   }
 
222
 
 
223
   close_all_svc_descriptors();
 
224
 
 
225
   for ( ;; )
 
226
   {
 
227
      cc = read( descriptor, buf, sizeof( buf ) ) ;
 
228
      if ( (cc == 0) || ((cc == -1) && (errno != EINTR)) )
 
229
         break ;
 
230
   }
 
231
   if( SVC_WAITS( svc ) ) /* Service forks, so close it */
 
232
      Sclose(descriptor);
 
233
}
 
234
 
 
235
 
 
236
static void dgram_discard( const struct server *serp )
 
237
{
 
238
   char buf[ 1 ] ;
 
239
 
 
240
   (void) recv( SERVER_FD( serp ), buf, sizeof( buf ), 0 ) ;
 
241
}
 
242
 
 
243
 
 
244
/*
 
245
 * Generate the current time using the SMTP format:
 
246
 *      02 FEB 1991 12:31:42 MST
 
247
 *
 
248
 * The result is placed in buf.
 
249
 * buflen is a value-result parameter. It indicates the size of
 
250
 * buf and on exit it has the length of the string placed in buf.
 
251
 */
 
252
static void daytime_protocol( char *buf, unsigned int *buflen )
 
253
{
 
254
   static const char *month_name[] =
 
255
      {
 
256
         "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
 
257
         "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
 
258
      } ;
 
259
   time_t      now ;
 
260
   struct tm   *tmp ;
 
261
   int         size = *buflen ;
 
262
#ifdef HAVE_STRFTIME
 
263
   int      cc ;
 
264
#endif
 
265
 
 
266
   (void) time( &now ) ;
 
267
   tmp = localtime( &now ) ;
 
268
#ifndef HAVE_STRFTIME
 
269
   strx_print( buflen, buf, size,
 
270
      "%02d %s %d %02d:%02d:%02d %s\r\n",
 
271
         tmp->tm_mday, month_name[ tmp->tm_mon ], 1900 + tmp->tm_year,
 
272
            tmp->tm_hour, tmp->tm_min, tmp->tm_sec, tmp->tm_zone ) ;
 
273
#else
 
274
   cc = strx_nprint( buf, size,
 
275
      "%02d %s %d %02d:%02d:%02d",
 
276
         tmp->tm_mday, month_name[ tmp->tm_mon ], 1900 + tmp->tm_year,
 
277
            tmp->tm_hour, tmp->tm_min, tmp->tm_sec ) ;
 
278
   if ( cc >= 0 ) { 
 
279
      *buflen = cc ;
 
280
      size -= cc ;
 
281
      cc = strftime( &buf[ *buflen ], size, " %Z\r\n", tmp ) ;
 
282
      *buflen += cc ;
 
283
   }
 
284
#endif
 
285
}
 
286
 
 
287
 
 
288
static void stream_daytime( const struct server *serp )
 
289
{
 
290
   char  time_buf[ BUFFER_SIZE ] ;
 
291
   unsigned int buflen = sizeof( time_buf ) ;
 
292
   int    descriptor = SERVER_FD( serp ) ;
 
293
   struct service *svc = SERVER_SERVICE( serp ) ;;
 
294
 
 
295
   if( SVC_WAITS( svc ) ) {
 
296
      descriptor = accept(descriptor, NULL, NULL);
 
297
      if ( descriptor == -1 ) {
 
298
         if ((errno == EMFILE) || (errno == ENFILE))
 
299
            cps_service_stop(svc, "no available descriptors");
 
300
         return;
 
301
      }
 
302
   }
 
303
   daytime_protocol( time_buf, &buflen ) ;
 
304
   (void) write_buf( descriptor, time_buf, buflen ) ;
 
305
   Sclose(descriptor);
 
306
}
 
307
 
 
308
 
 
309
static void dgram_daytime( const struct server *serp )
 
310
{
 
311
   char            time_buf[ BUFFER_SIZE ] ;
 
312
   union xsockaddr lsin ;
 
313
   unsigned int    sin_len     = 0 ;
 
314
   unsigned int    buflen      = sizeof( time_buf ) ;
 
315
   int             descriptor  = SERVER_FD( serp ) ;
 
316
   const char     *func       = "dgram_daytime";
 
317
 
 
318
   if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
 
319
      sin_len = sizeof( struct sockaddr_in );
 
320
   else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
 
321
      sin_len = sizeof( struct sockaddr_in6 );
 
322
 
 
323
   if ( recvfrom( descriptor, time_buf, sizeof( time_buf ), 0,
 
324
            SA( &lsin ), &sin_len ) == -1 )
 
325
      return ;
 
326
 
 
327
   if( bad_port_check(&lsin, func) != 0 ) return;
 
328
 
 
329
   daytime_protocol( time_buf, &buflen ) ;
 
330
   
 
331
   (void) sendto( descriptor, time_buf, buflen, 0, SA(&lsin), sizeof( lsin ) ) ;
 
332
}
 
333
 
 
334
 
 
335
#define TIME_OFFSET         2208988800UL
 
336
 
 
337
/*
 
338
 * We always report the time as 32 bits in network-byte-order
 
339
 */
 
340
static void time_protocol( unsigned char *timep )
 
341
{
 
342
   time_t now ;
 
343
   unsigned long base1900;
 
344
 
 
345
   (void) time( &now ) ;
 
346
   base1900 = (unsigned long)now + TIME_OFFSET ;
 
347
   timep[0] = base1900 >> 24;
 
348
   timep[1] = base1900 >> 16;
 
349
   timep[2] = base1900 >> 8;
 
350
   timep[3] = base1900;
 
351
 
 
352
}
 
353
 
 
354
 
 
355
static void stream_time( const struct server *serp )
 
356
{
 
357
   unsigned char time_buf[4];
 
358
   int descriptor = SERVER_FD( serp );
 
359
   struct service *svc = SERVER_SERVICE( serp );
 
360
 
 
361
   if( SVC_WAITS( svc ) ) {
 
362
      descriptor = accept(descriptor, NULL, NULL);
 
363
      if ( descriptor == -1 ) {
 
364
         if ((errno == EMFILE) || (errno == ENFILE))
 
365
            cps_service_stop(svc, "no available descriptors");
 
366
         return;
 
367
      }
 
368
   }
 
369
 
 
370
   time_protocol( time_buf ) ;
 
371
   (void) write_buf( descriptor, (char *) time_buf, 4 ) ;
 
372
 
 
373
   Sclose(descriptor);
 
374
}
 
375
 
 
376
 
 
377
static void dgram_time( const struct server *serp )
 
378
{
 
379
   char     buf[ 1 ] ;
 
380
   unsigned char time_buf[4];
 
381
   union xsockaddr lsin ;
 
382
   unsigned int    sin_len = 0 ;
 
383
   int             fd      = SERVER_FD( serp ) ;
 
384
   const char     *func    = "dgram_daytime";
 
385
 
 
386
   if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
 
387
      sin_len = sizeof( struct sockaddr_in );
 
388
   else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
 
389
      sin_len = sizeof( struct sockaddr_in6 );
 
390
 
 
391
   if ( recvfrom( fd, buf, sizeof( buf ), 0, SA( &lsin ), &sin_len ) == -1 )
 
392
      return ;
 
393
   if( bad_port_check(&lsin, func) != 0 ) return;
 
394
 
 
395
   time_protocol( time_buf ) ;
 
396
   (void) sendto( fd, (char *) time_buf, 4, 0, SA( &lsin ), sin_len ) ;
 
397
}
 
398
 
 
399
 
 
400
#define ASCII_PRINTABLE_CHARS     94
 
401
#define LINE_LENGTH               72
 
402
 
 
403
#define RING_BUF_SIZE             ASCII_PRINTABLE_CHARS + LINE_LENGTH
 
404
 
 
405
static char *ring_buf = NULL ;
 
406
static char *ring ;
 
407
 
 
408
 
 
409
#define ASCII_START          ( ' ' + 1 )
 
410
#define ASCII_END            126
 
411
 
 
412
#define min( a, b )          ((a)<(b) ? (a) : (b))
 
413
 
 
414
static char *generate_line( char *buf, unsigned int len )
 
415
{
 
416
   unsigned int line_len = min( LINE_LENGTH, len-2 ) ;
 
417
 
 
418
   if ( len < 2 )       /* If len < 2, min will be wrong */
 
419
      return( NULL ) ;
 
420
 
 
421
   /* This never gets freed.  That's ok, because the reference to it is
 
422
    * always kept for future reference.
 
423
    */
 
424
   if ( (ring_buf == NULL) && ((ring_buf = malloc(RING_BUF_SIZE)) == NULL) ) 
 
425
      return(NULL);
 
426
 
 
427
   if ( ring == NULL )
 
428
   {
 
429
      char ch ;
 
430
      char *p ;
 
431
 
 
432
      for ( p = ring_buf, ch = ASCII_START ;
 
433
            p <= &ring_buf[ RING_BUF_SIZE - 1 ] ; p++ )
 
434
      {
 
435
         *p = ch++ ;
 
436
         if ( ch == ASCII_END )
 
437
            ch = ASCII_START ;
 
438
      }
 
439
      ring = ring_buf ;
 
440
   }
 
441
   (void) memcpy( buf, ring, line_len ) ;
 
442
   buf[ line_len   ] = '\r' ;
 
443
   buf[ line_len+1 ] = '\n' ;
 
444
 
 
445
   ring++ ;
 
446
   if ( &ring_buf[ RING_BUF_SIZE - 1 ] - ring + 1 < LINE_LENGTH )
 
447
      ring = ring_buf ;
 
448
   return( buf ) ;
 
449
}
 
450
 
 
451
 
 
452
static void stream_chargen( const struct server *serp )
 
453
{
 
454
   char   line_buf[ LINE_LENGTH+2 ] ;
 
455
   int    descriptor = SERVER_FD( serp ) ;
 
456
   struct service *svc = SERVER_SERVICE( serp );
 
457
 
 
458
   if( SVC_WAITS( svc ) ) {
 
459
      descriptor = accept(descriptor, NULL, NULL);
 
460
      if ( descriptor == -1 ) {
 
461
         if ((errno == EMFILE) || (errno == ENFILE))
 
462
            cps_service_stop(svc, "no available descriptors");
 
463
         return;
 
464
      }
 
465
   }
 
466
 
 
467
   (void) shutdown( descriptor, 0 ) ;
 
468
   close_all_svc_descriptors();
 
469
 
 
470
   for ( ;; )
 
471
   {
 
472
      if ( generate_line( line_buf, sizeof( line_buf ) ) == NULL )
 
473
         break ;
 
474
      if ( write_buf( descriptor, line_buf, sizeof( line_buf ) ) == FAILED )
 
475
         break ;
 
476
   }
 
477
   if( SVC_WAITS( svc ) ) /* Service forks, so close it */
 
478
      Sclose(descriptor);
 
479
}
 
480
 
 
481
 
 
482
static void dgram_chargen( const struct server *serp )
 
483
{
 
484
   char            buf[ BUFFER_SIZE ] ;
 
485
   char            *p ;
 
486
   unsigned int    len ;
 
487
   union xsockaddr lsin ;
 
488
   unsigned int    sin_len = 0 ;
 
489
   int             fd      = SERVER_FD( serp ) ;
 
490
   unsigned int    left    = sizeof( buf ) ;
 
491
   const char     *func    = "dgram_chargen";
 
492
 
 
493
   if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
 
494
      sin_len = sizeof( struct sockaddr_in );
 
495
   else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
 
496
      sin_len = sizeof( struct sockaddr_in6 );
 
497
 
 
498
   if ( recvfrom( fd, buf, sizeof( buf ), 0, SA( &lsin ), &sin_len ) == -1 )
 
499
      return ;
 
500
 
 
501
#if BUFFER_SIZE < LINE_LENGTH+2
 
502
   bad_variable = 1 ;      /* this will cause a compilation error */
 
503
#endif
 
504
 
 
505
   if( bad_port_check(&lsin, func) != 0 ) return;
 
506
 
 
507
   for ( p = buf ; left > 2 ; left -= len, p += len )
 
508
   {
 
509
      len = min( LINE_LENGTH+2, left ) ;
 
510
      if ( generate_line( p, len ) == NULL )
 
511
         break ;
 
512
   }
 
513
   (void) sendto( fd, buf, p-buf, 0, SA( &lsin ), sin_len ) ;
 
514
}
 
515
 
 
516
 
 
517
/*  Handle a request for a tcpmux service. 
 
518
 *  It's helpful to remember here that we are now a child of the original
 
519
 *  xinetd process. We were forked to keep the parent from blocking
 
520
 *  when we try to read the service name off'n the socket connection.
 
521
 *  Serp still points to an actual tcpmux 'server', or at least the
 
522
 *  service pointer of serp is valid.
 
523
 */
 
524
 
 
525
static void tcpmux_handler( const struct server *serp )
 
526
{
 
527
   char      svc_name[ BUFFER_SIZE ] ;
 
528
   int       cc ;
 
529
   int       descriptor = SERVER_FD( serp ) ;
 
530
   const     struct service *svc = SERVER_SERVICE( serp ) ;
 
531
   unsigned  u;
 
532
   struct    service *sp = NULL;
 
533
   struct    server server, *nserp;
 
534
   struct    service_config *scp = NULL;
 
535
 
 
536
   close_all_svc_descriptors();
 
537
 
 
538
   /*  Read in the name of the service in the format "svc_name\r\n".
 
539
    *
 
540
    *  XXX: should loop on partial reads (could probably use Sread() if
 
541
    *  it wasn't thrown out of xinetd source code a few revisions back).
 
542
    */
 
543
   do
 
544
   {
 
545
      cc = read( descriptor, svc_name, sizeof( svc_name ) ) ;
 
546
   } while (cc == -1 && errno == EINTR);
 
547
 
 
548
   if ( cc <= 0 )
 
549
   {
 
550
      msg(LOG_ERR, "tcpmux_handler", "read failed");
 
551
      exit(0);
 
552
   }
 
553
 
 
554
   if ( ( cc <= 2 ) ||
 
555
        ( ( svc_name[cc - 1] != '\n' ) || ( svc_name[cc - 2] != '\r' ) ) )
 
556
   {
 
557
      if ( debug.on )
 
558
         msg(LOG_DEBUG, "tcpmux_handler", "Invalid service name format.");
 
559
      
 
560
      exit(0);
 
561
   }
 
562
 
 
563
   svc_name[cc - 2] = '\0';  /*  Remove \r\n for compare */
 
564
 
 
565
   if ( debug.on )
 
566
   {
 
567
      msg(LOG_DEBUG, "tcpmux_handler", "Input (%d bytes) %s as service name.",
 
568
          cc, svc_name);
 
569
   }
 
570
 
 
571
   /*  Search the services for the a match on name.
 
572
    */
 
573
 
 
574
   for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
 
575
   {
 
576
      sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
 
577
 
 
578
      if ( strcasecmp( svc_name, SC_NAME( SVC_CONF( sp ) ) ) == 0 )
 
579
      {
 
580
         /*  Found the pointer. Validate its type.
 
581
          */
 
582
         scp = SVC_CONF( sp );
 
583
/*
 
584
         if ( ! SVC_IS_MUXCLIENT( sp ) )
 
585
         {
 
586
            if ( debug.on )
 
587
            {
 
588
               msg(LOG_DEBUG, "tcpmux_handler", "Non-tcpmux service name: %s.",
 
589
                   svc_name);
 
590
            }
 
591
            exit(0);
 
592
         }
 
593
*/
 
594
 
 
595
         /*  Send the accept string if we're a PLUS (+) client.
 
596
          */
 
597
 
 
598
         if ( SVC_IS_MUXPLUSCLIENT( sp ) )
 
599
         {
 
600
            if ( Swrite( descriptor, TCPMUX_ACK, sizeof( TCPMUX_ACK ) ) !=
 
601
                 sizeof( TCPMUX_ACK ) )
 
602
            {
 
603
                msg(LOG_ERR, "tcpmux_handler", "Ack write failed for %s.",
 
604
                    svc_name);
 
605
                exit(0);
 
606
            }
 
607
         }
 
608
         break;  /*  Time to get on with the service */
 
609
      }
 
610
      continue;  /*  Keep looking */
 
611
   }
 
612
 
 
613
   if ( u >= pset_count( SERVICES( ps ) ) )
 
614
   {
 
615
      if ( debug.on )
 
616
      {
 
617
         msg(LOG_DEBUG, "tcpmux_handler", "Service name %s not found.",
 
618
             svc_name);
 
619
      }
 
620
      exit(0);
 
621
   }
 
622
 
 
623
   if( SVC_WAITS( svc ) ) /* Service forks, so close it */
 
624
      Sclose(descriptor);
 
625
 
 
626
   server.svr_sp = sp;
 
627
   server.svr_conn = SERVER_CONNECTION(serp);
 
628
   nserp = server_alloc(&server);
 
629
   if( SC_IS_INTERNAL( scp ) ) {
 
630
      SC_INTERNAL(scp, nserp);
 
631
   } else {
 
632
      exec_server(nserp);
 
633
   }
 
634
}
 
635