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.
10
#include <sys/types.h>
11
#include <sys/socket.h>
12
#include <netinet/in.h>
13
#include <arpa/inet.h>
28
#include "connection.h"
36
#include "libportable.h"
42
#define BUFFER_SIZE 1024
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 *);
58
* SG - This is the call sequence to get to a built-in service
61
* svc_request service.c
62
* svc_handle -- aka svc_handler_func -- aka svc_generic_handler service.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
70
static const struct builtin_service builtin_services[] =
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 } }
89
const builtin_s *builtin_find( const char *service_name, int type )
91
const builtin_s *bsp ;
92
const char *func = "builtin_find" ;
94
if ( (bsp = builtin_lookup( builtin_services, service_name, type )) )
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";
103
type_name = sock_type->name;
104
msg( LOG_ERR, func, "No such internal service: %s/%s - DISABLING",
105
service_name, type_name ) ;
111
const builtin_s *builtin_lookup( const struct builtin_service services[],
112
const char *service_name,
115
const struct builtin_service *bsp ;
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 ) ;
125
* The rest of this file contains the functions that implement the
130
static void stream_echo( const struct server *serp )
132
char buf[ BUFFER_SIZE ] ;
134
int descriptor = SERVER_FD( serp ) ;
135
struct service *svc = SERVER_SERVICE( serp ) ;;
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");
146
close_all_svc_descriptors();
150
cc = read( descriptor, buf, sizeof( buf ) ) ;
154
if ( errno == EINTR )
160
if ( write_buf( descriptor, buf, cc ) == FAILED )
163
if( SVC_WAITS( svc ) ) /* Service forks, so close it */
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.
171
static int bad_port_check( const union xsockaddr *sa, const char *func )
175
port = ntohs( xaddrport( sa ) );
178
msg(LOG_WARNING, func,
179
"Possible Denial of Service attack from %s %d", xaddrname(sa), port);
186
static void dgram_echo( const struct server *serp )
188
char buf[ DATAGRAM_SIZE ] ;
189
union xsockaddr lsin;
191
unsigned int sin_len = 0;
192
int descriptor = SERVER_FD( serp ) ;
193
const char *func = "dgram_echo";
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 );
200
cc = recvfrom( descriptor, buf, sizeof( buf ), 0, SA( &lsin ), &sin_len ) ;
202
if( bad_port_check(&lsin, func) != 0 ) return;
203
(void) sendto( descriptor, buf, cc, 0, SA( &lsin ), sizeof( lsin ) ) ;
207
static void stream_discard( const struct server *serp )
209
char buf[ BUFFER_SIZE ] ;
211
int descriptor = SERVER_FD( serp ) ;
212
struct service *svc = SERVER_SERVICE( serp ) ;;
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");
223
close_all_svc_descriptors();
227
cc = read( descriptor, buf, sizeof( buf ) ) ;
228
if ( (cc == 0) || ((cc == -1) && (errno != EINTR)) )
231
if( SVC_WAITS( svc ) ) /* Service forks, so close it */
236
static void dgram_discard( const struct server *serp )
240
(void) recv( SERVER_FD( serp ), buf, sizeof( buf ), 0 ) ;
245
* Generate the current time using the SMTP format:
246
* 02 FEB 1991 12:31:42 MST
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.
252
static void daytime_protocol( char *buf, unsigned int *buflen )
254
static const char *month_name[] =
256
"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
257
"JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
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 ) ;
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 ) ;
281
cc = strftime( &buf[ *buflen ], size, " %Z\r\n", tmp ) ;
288
static void stream_daytime( const struct server *serp )
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 ) ;;
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");
303
daytime_protocol( time_buf, &buflen ) ;
304
(void) write_buf( descriptor, time_buf, buflen ) ;
309
static void dgram_daytime( const struct server *serp )
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";
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 );
323
if ( recvfrom( descriptor, time_buf, sizeof( time_buf ), 0,
324
SA( &lsin ), &sin_len ) == -1 )
327
if( bad_port_check(&lsin, func) != 0 ) return;
329
daytime_protocol( time_buf, &buflen ) ;
331
(void) sendto( descriptor, time_buf, buflen, 0, SA(&lsin), sizeof( lsin ) ) ;
335
#define TIME_OFFSET 2208988800UL
338
* We always report the time as 32 bits in network-byte-order
340
static void time_protocol( unsigned char *timep )
343
unsigned long base1900;
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;
355
static void stream_time( const struct server *serp )
357
unsigned char time_buf[4];
358
int descriptor = SERVER_FD( serp );
359
struct service *svc = SERVER_SERVICE( serp );
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");
370
time_protocol( time_buf ) ;
371
(void) write_buf( descriptor, (char *) time_buf, 4 ) ;
377
static void dgram_time( const struct server *serp )
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";
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 );
391
if ( recvfrom( fd, buf, sizeof( buf ), 0, SA( &lsin ), &sin_len ) == -1 )
393
if( bad_port_check(&lsin, func) != 0 ) return;
395
time_protocol( time_buf ) ;
396
(void) sendto( fd, (char *) time_buf, 4, 0, SA( &lsin ), sin_len ) ;
400
#define ASCII_PRINTABLE_CHARS 94
401
#define LINE_LENGTH 72
403
#define RING_BUF_SIZE ASCII_PRINTABLE_CHARS + LINE_LENGTH
405
static char *ring_buf = NULL ;
409
#define ASCII_START ( ' ' + 1 )
410
#define ASCII_END 126
412
#define min( a, b ) ((a)<(b) ? (a) : (b))
414
static char *generate_line( char *buf, unsigned int len )
416
unsigned int line_len = min( LINE_LENGTH, len-2 ) ;
418
if ( len < 2 ) /* If len < 2, min will be wrong */
421
/* This never gets freed. That's ok, because the reference to it is
422
* always kept for future reference.
424
if ( (ring_buf == NULL) && ((ring_buf = malloc(RING_BUF_SIZE)) == NULL) )
432
for ( p = ring_buf, ch = ASCII_START ;
433
p <= &ring_buf[ RING_BUF_SIZE - 1 ] ; p++ )
436
if ( ch == ASCII_END )
441
(void) memcpy( buf, ring, line_len ) ;
442
buf[ line_len ] = '\r' ;
443
buf[ line_len+1 ] = '\n' ;
446
if ( &ring_buf[ RING_BUF_SIZE - 1 ] - ring + 1 < LINE_LENGTH )
452
static void stream_chargen( const struct server *serp )
454
char line_buf[ LINE_LENGTH+2 ] ;
455
int descriptor = SERVER_FD( serp ) ;
456
struct service *svc = SERVER_SERVICE( serp );
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");
467
(void) shutdown( descriptor, 0 ) ;
468
close_all_svc_descriptors();
472
if ( generate_line( line_buf, sizeof( line_buf ) ) == NULL )
474
if ( write_buf( descriptor, line_buf, sizeof( line_buf ) ) == FAILED )
477
if( SVC_WAITS( svc ) ) /* Service forks, so close it */
482
static void dgram_chargen( const struct server *serp )
484
char buf[ BUFFER_SIZE ] ;
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";
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 );
498
if ( recvfrom( fd, buf, sizeof( buf ), 0, SA( &lsin ), &sin_len ) == -1 )
501
#if BUFFER_SIZE < LINE_LENGTH+2
502
bad_variable = 1 ; /* this will cause a compilation error */
505
if( bad_port_check(&lsin, func) != 0 ) return;
507
for ( p = buf ; left > 2 ; left -= len, p += len )
509
len = min( LINE_LENGTH+2, left ) ;
510
if ( generate_line( p, len ) == NULL )
513
(void) sendto( fd, buf, p-buf, 0, SA( &lsin ), sin_len ) ;
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.
525
static void tcpmux_handler( const struct server *serp )
527
char svc_name[ BUFFER_SIZE ] ;
529
int descriptor = SERVER_FD( serp ) ;
530
const struct service *svc = SERVER_SERVICE( serp ) ;
532
struct service *sp = NULL;
533
struct server server, *nserp;
534
struct service_config *scp = NULL;
536
close_all_svc_descriptors();
538
/* Read in the name of the service in the format "svc_name\r\n".
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).
545
cc = read( descriptor, svc_name, sizeof( svc_name ) ) ;
546
} while (cc == -1 && errno == EINTR);
550
msg(LOG_ERR, "tcpmux_handler", "read failed");
555
( ( svc_name[cc - 1] != '\n' ) || ( svc_name[cc - 2] != '\r' ) ) )
558
msg(LOG_DEBUG, "tcpmux_handler", "Invalid service name format.");
563
svc_name[cc - 2] = '\0'; /* Remove \r\n for compare */
567
msg(LOG_DEBUG, "tcpmux_handler", "Input (%d bytes) %s as service name.",
571
/* Search the services for the a match on name.
574
for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
576
sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
578
if ( strcasecmp( svc_name, SC_NAME( SVC_CONF( sp ) ) ) == 0 )
580
/* Found the pointer. Validate its type.
582
scp = SVC_CONF( sp );
584
if ( ! SVC_IS_MUXCLIENT( sp ) )
588
msg(LOG_DEBUG, "tcpmux_handler", "Non-tcpmux service name: %s.",
595
/* Send the accept string if we're a PLUS (+) client.
598
if ( SVC_IS_MUXPLUSCLIENT( sp ) )
600
if ( Swrite( descriptor, TCPMUX_ACK, sizeof( TCPMUX_ACK ) ) !=
601
sizeof( TCPMUX_ACK ) )
603
msg(LOG_ERR, "tcpmux_handler", "Ack write failed for %s.",
608
break; /* Time to get on with the service */
610
continue; /* Keep looking */
613
if ( u >= pset_count( SERVICES( ps ) ) )
617
msg(LOG_DEBUG, "tcpmux_handler", "Service name %s not found.",
623
if( SVC_WAITS( svc ) ) /* Service forks, so close it */
627
server.svr_conn = SERVER_CONNECTION(serp);
628
nserp = server_alloc(&server);
629
if( SC_IS_INTERNAL( scp ) ) {
630
SC_INTERNAL(scp, nserp);