static void stream_discard( const struct server *serp ) { char buf[ BUFFER_SIZE ] ; int cc ; int descriptor = SERVER_FD( serp ) ; struct service *svc = SERVER_SERVICE( serp ) ;; if( SVC_WAITS( svc ) ) { descriptor = accept(descriptor, NULL, NULL); if ( descriptor == -1 ) { if ((errno == EMFILE) || (errno == ENFILE)) cps_service_stop(svc, "no available descriptors"); return; } } close_all_svc_descriptors(); for ( ;; ) { cc = read( descriptor, buf, sizeof( buf ) ) ; if ( (cc == 0) || ((cc == -1) && (errno != EINTR)) ) break ; } if( SVC_WAITS( svc ) ) /* Service forks, so close it */ Sclose(descriptor); }
static void stream_chargen( const struct server *serp ) { char line_buf[ LINE_LENGTH+2 ] ; int descriptor = SERVER_FD( serp ) ; struct service *svc = SERVER_SERVICE( serp ); if( SVC_WAITS( svc ) ) { descriptor = accept(descriptor, NULL, NULL); if ( descriptor == -1 ) { if ((errno == EMFILE) || (errno == ENFILE)) cps_service_stop(svc, "no available descriptors"); return; } } (void) shutdown( descriptor, 0 ) ; close_all_svc_descriptors(); for ( ;; ) { if ( generate_line( line_buf, sizeof( line_buf ) ) == NULL ) break ; if ( write_buf( descriptor, line_buf, sizeof( line_buf ) ) == FAILED ) break ; } if( SVC_WAITS( svc ) ) /* Service forks, so close it */ Sclose(descriptor); }
static void stream_echo( const struct server *serp ) { char buf[ BUFFER_SIZE ] ; ssize_t cc ; int descriptor = SERVER_FD( serp ) ; struct service *svc = SERVER_SERVICE( serp ) ;; if( SVC_WAITS( svc ) ) { descriptor = accept(descriptor, NULL, NULL); if ( descriptor == -1 ) { if ((errno == EMFILE) || (errno == ENFILE)) cps_service_stop(svc, "no available descriptors"); return; } } close_all_svc_descriptors(); for ( ;; ) { cc = read( descriptor, buf, sizeof( buf ) ) ; if ( cc == 0 ) break ; if ( cc == (ssize_t)-1 ) { if ( errno == EINTR ) continue ; else break ; } if ( write_buf( descriptor, buf, cc ) == FAILED ) break ; } if( SVC_WAITS( svc ) ) /* Service forks, so close it */ Sclose(descriptor); }
/* This function gets called from child.c after we have been forked */ void redir_handler( struct server *serp ) { struct service *sp = SERVER_SERVICE( serp ); struct service_config *scp = SVC_CONF( sp ); int RedirDescrip = SERVER_FD( serp ); int maxfd, num_read, num_wrote=0, ret=0; unsigned int sin_len = 0; unsigned long bytes_in = 0, bytes_out = 0; int no_to_nagle = 1; int on = 1, v6on; char buff[NET_BUFFER]; fd_set rdfd, msfd; struct timeval *timep = NULL; const char *func = "redir_handler"; union xsockaddr serveraddr ; if( signal(SIGPIPE, redir_sigpipe) == SIG_ERR ) msg(LOG_ERR, func, "unable to setup signal handler"); close_all_svc_descriptors(); /* If it's a tcp service we are redirecting */ if( scp->sc_protocol.value == IPPROTO_TCP ) { memcpy(&serveraddr, scp->sc_redir_addr, sizeof(serveraddr)); if( serveraddr.sa_in.sin_family == AF_INET ) { sin_len = sizeof( struct sockaddr_in ); RedirServerFd = socket(AF_INET, SOCK_STREAM, 0); } else if( serveraddr.sa_in.sin_family == AF_INET6 ) { sin_len = sizeof( struct sockaddr_in6 ); RedirServerFd = socket(AF_INET6, SOCK_STREAM, 0); } else { msg(LOG_ERR, func, "not a valid protocol. Use IPv4 or IPv6."); exit(0); } if( RedirServerFd < 0 ) { msg(LOG_ERR, func, "cannot create socket: %m"); exit(0); } if( SC_IPV6( scp ) ) { if( SC_V6ONLY( scp ) ) { v6on = 1; } else { v6on = 0; } #ifdef IPV6_V6ONLY if( setsockopt(RedirServerFd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&v6on, sizeof(v6on)) < 0 ) { msg( LOG_ERR, func, "Setting IPV6_V6ONLY option failed (%m)" ); } #endif } if( SC_KEEPALIVE( scp ) ) if (setsockopt(RedirServerFd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof( on ) ) < 0 ) msg(LOG_ERR, func, "setsockopt SO_KEEPALIVE RedirServerFd failed: %m"); if( serveraddr.sa_in.sin_family == AF_INET ) serveraddr.sa_in.sin_port = htons(serveraddr.sa_in.sin_port); if( serveraddr.sa_in.sin_family == AF_INET6 ) serveraddr.sa_in6.sin6_port = htons(serveraddr.sa_in6.sin6_port); if( connect(RedirServerFd, &serveraddr.sa, sin_len) < 0 ) { msg(LOG_ERR, func, "can't connect to remote host %s: %m", xaddrname( &serveraddr ) ); exit(0); } /* connection now established */ if (setsockopt(RedirServerFd, IPPROTO_TCP, TCP_NODELAY, (char *) &no_to_nagle, sizeof( on ) ) < 0) { msg(LOG_ERR, func, "setsockopt RedirServerFd failed: %m"); } if (setsockopt(RedirDescrip, IPPROTO_TCP, TCP_NODELAY, (char *) &no_to_nagle, sizeof( on ) ) < 0) { msg(LOG_ERR, func, "setsockopt RedirDescrip failed: %m"); } maxfd = (RedirServerFd > RedirDescrip)?RedirServerFd:RedirDescrip; FD_ZERO(&msfd); FD_SET(RedirDescrip, &msfd); FD_SET(RedirServerFd, &msfd); while(1) { memcpy(&rdfd, &msfd, sizeof(rdfd)); if (select(maxfd + 1, &rdfd, (fd_set *)0, (fd_set *)0, timep) <= 0) { /* place for timeout code, currently does not time out */ break; } if (FD_ISSET(RedirDescrip, &rdfd)) { do { num_read = read(RedirDescrip, buff, sizeof(buff)); if (num_read == -1 && errno == EINTR) continue; if (num_read <= 0) goto REDIROUT; bytes_in += num_read; } while (num_read < 0); /* Loop until we have written everything * that was read */ num_wrote = 0; while( num_wrote < num_read ) { ret = write(RedirServerFd, buff + num_wrote, num_read - num_wrote); if (ret == -1 && errno == EINTR) continue; if (ret <= 0) goto REDIROUT; num_wrote += ret; } } if (FD_ISSET(RedirServerFd, &rdfd)) { do { num_read = read(RedirServerFd, buff, sizeof(buff)); if (num_read == -1 && errno == EINTR) continue; if (num_read <= 0) goto REDIROUT; bytes_out += num_read; } while (num_read < 0); /* Loop until we have written everything * that was read */ num_wrote = 0; while( num_wrote < num_read ) { ret = write(RedirDescrip, buff + num_wrote, num_read - num_wrote); if (ret == -1 && errno == EINTR) continue; if (ret <= 0) goto REDIROUT; num_wrote += ret; } } } REDIROUT: if( M_IS_SET( (scp)->sc_log_on_success, LO_TRAFFIC ) ) { svc_logprint( SERVER_CONNSERVICE( serp ), "TRAFFIC", "in=%lu(bytes) out=%lu(bytes)", bytes_in, bytes_out ); } exit(0); } msg(LOG_ERR, func, "redirect with any protocol other than tcp is not supported at this time."); exit(0); }
static void tcpmux_handler( const struct server *serp ) { char svc_name[ BUFFER_SIZE ] ; int cc ; int descriptor = SERVER_FD( serp ) ; const struct service *svc = SERVER_SERVICE( serp ) ; unsigned u; struct service *sp = NULL; struct server server, *nserp; struct service_config *scp = NULL; close_all_svc_descriptors(); /* Read in the name of the service in the format "svc_name\r\n". * * XXX: should loop on partial reads (could probably use Sread() if * it wasn't thrown out of xinetd source code a few revisions back). */ do { cc = read( descriptor, svc_name, sizeof( svc_name ) ) ; } while (cc == -1 && errno == EINTR); if ( cc <= 0 ) { msg(LOG_ERR, "tcpmux_handler", "read failed"); exit(0); } if ( ( cc <= 2 ) || ( ( svc_name[cc - 1] != '\n' ) || ( svc_name[cc - 2] != '\r' ) ) ) { if ( debug.on ) msg(LOG_DEBUG, "tcpmux_handler", "Invalid service name format."); exit(0); } svc_name[cc - 2] = '\0'; /* Remove \r\n for compare */ if ( debug.on ) { msg(LOG_DEBUG, "tcpmux_handler", "Input (%d bytes) %s as service name.", cc, svc_name); } /* Search the services for the a match on name. */ for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ ) { sp = SP( pset_pointer( SERVICES( ps ), u ) ) ; if ( strcasecmp( svc_name, SC_NAME( SVC_CONF( sp ) ) ) == 0 ) { /* Found the pointer. Validate its type. */ scp = SVC_CONF( sp ); /* if ( ! SVC_IS_MUXCLIENT( sp ) ) { if ( debug.on ) { msg(LOG_DEBUG, "tcpmux_handler", "Non-tcpmux service name: %s.", svc_name); } exit(0); } */ /* Send the accept string if we're a PLUS (+) client. */ if ( SVC_IS_MUXPLUSCLIENT( sp ) ) { if ( Swrite( descriptor, TCPMUX_ACK, sizeof( TCPMUX_ACK ) ) != sizeof( TCPMUX_ACK ) ) { msg(LOG_ERR, "tcpmux_handler", "Ack write failed for %s.", svc_name); exit(0); } } break; /* Time to get on with the service */ } continue; /* Keep looking */ } if ( u >= pset_count( SERVICES( ps ) ) ) { if ( debug.on ) { msg(LOG_DEBUG, "tcpmux_handler", "Service name %s not found.", svc_name); } exit(0); } if( SVC_WAITS( svc ) ) /* Service forks, so close it */ Sclose(descriptor); server.svr_sp = sp; server.svr_conn = SERVER_CONNECTION(serp); nserp = server_alloc(&server); if( SC_IS_INTERNAL( scp ) ) { SC_INTERNAL(scp, nserp); } else { exec_server(nserp); } }