mirror of
https://github.com/moparisthebest/sslh
synced 2024-11-21 16:45:03 -05:00
167 lines
3.9 KiB
C
167 lines
3.9 KiB
C
|
/* echosrv: a simple line echo server with optional prefix adding.
|
||
|
*
|
||
|
* echsrv --listen localhost6:1234 --prefix "ssl: "
|
||
|
*
|
||
|
* This will bind to 1234, and echo every line pre-pending "ssl: ". This is
|
||
|
* used for testing: we create several such servers with different prefixes,
|
||
|
* then we connect test clients that can then check they get the proper data
|
||
|
* back (thus testing that shoveling works both ways) with the correct prefix
|
||
|
* (thus testing it connected to the expected service).
|
||
|
* **/
|
||
|
|
||
|
#define _GNU_SOURCE
|
||
|
#include <sys/types.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <string.h>
|
||
|
#include <unistd.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <stdio.h>
|
||
|
#include <signal.h>
|
||
|
#include <sys/socket.h>
|
||
|
#include <sys/wait.h>
|
||
|
#include <netinet/in.h>
|
||
|
#include <arpa/inet.h>
|
||
|
#include <netdb.h>
|
||
|
#include <pwd.h>
|
||
|
#include <syslog.h>
|
||
|
#include <libgen.h>
|
||
|
#include <getopt.h>
|
||
|
|
||
|
#include "common.h"
|
||
|
|
||
|
/* Added to make the code compilable under CYGWIN
|
||
|
* */
|
||
|
#ifndef SA_NOCLDWAIT
|
||
|
#define SA_NOCLDWAIT 0
|
||
|
#endif
|
||
|
|
||
|
const char* USAGE_STRING =
|
||
|
"echosrv\n" \
|
||
|
"usage:\n" \
|
||
|
"\techosrv [-v] --listen <address:port> [--prefix <prefix>]\n"
|
||
|
"-v: verbose\n" \
|
||
|
"--listen: address to listen on. Can be specified multiple times.\n" \
|
||
|
"--prefix: add specified prefix before every line echoed.\n"
|
||
|
"";
|
||
|
|
||
|
const char* server_type = "echsrv"; /* keep setup_syslog happy */
|
||
|
|
||
|
/*
|
||
|
* Settings that depend on the command line.
|
||
|
*/
|
||
|
char* prefix = "";
|
||
|
int port;
|
||
|
|
||
|
void parse_cmdline(int argc, char* argv[])
|
||
|
{
|
||
|
int c;
|
||
|
struct option options[] = {
|
||
|
{ "verbose", no_argument, &verbose, 1 },
|
||
|
{ "numeric", no_argument, &numeric, 1 },
|
||
|
{ "listen", required_argument, 0, 'l' },
|
||
|
{ "prefix", required_argument, 0, 'p' },
|
||
|
};
|
||
|
struct addrinfo **a;
|
||
|
|
||
|
while ((c = getopt_long_only(argc, argv, "l:p:", options, NULL)) != -1) {
|
||
|
if (c == 0) continue;
|
||
|
|
||
|
switch (c) {
|
||
|
|
||
|
case 'l':
|
||
|
/* find the end of the listen list */
|
||
|
for (a = &addr_listen; *a; a = &((*a)->ai_next));
|
||
|
/* append the specified addresses */
|
||
|
resolve_name(a, optarg);
|
||
|
break;
|
||
|
|
||
|
case 'p':
|
||
|
prefix = optarg;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
fprintf(stderr, "%s", USAGE_STRING);
|
||
|
exit(2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!addr_listen) {
|
||
|
fprintf(stderr, "No listening port specified\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void start_echo(int fd)
|
||
|
{
|
||
|
fd_set fds;
|
||
|
int res;
|
||
|
char buffer[1 << 20];
|
||
|
char* ret;
|
||
|
FILE *socket;
|
||
|
|
||
|
FD_ZERO(&fds);
|
||
|
|
||
|
socket = fdopen(fd, "r+");
|
||
|
if (!socket) {
|
||
|
CHECK_RES_DIE(-1, "fdopen");
|
||
|
}
|
||
|
|
||
|
while (1) {
|
||
|
ret = fgets(buffer, sizeof(buffer), socket);
|
||
|
if (!ret) {
|
||
|
fprintf(stderr, "%s", strerror(ferror(socket)));
|
||
|
return;
|
||
|
}
|
||
|
res = fprintf(socket, "%s%s", prefix, buffer);
|
||
|
if (res < 0) {
|
||
|
fprintf(stderr, "%s", strerror(ferror(socket)));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
fflush(socket);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void main_loop(int listen_sockets[], int num_addr_listen)
|
||
|
{
|
||
|
int in_socket, i;
|
||
|
|
||
|
for (i = 0; i < num_addr_listen; i++) {
|
||
|
if (!fork()) {
|
||
|
while (1)
|
||
|
{
|
||
|
in_socket = accept(listen_sockets[i], 0, 0);
|
||
|
if (verbose) fprintf(stderr, "accepted fd %d\n", in_socket);
|
||
|
|
||
|
if (!fork())
|
||
|
{
|
||
|
close(listen_sockets[i]);
|
||
|
start_echo(in_socket);
|
||
|
exit(0);
|
||
|
}
|
||
|
close(in_socket);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
wait(NULL);
|
||
|
}
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
|
||
|
extern char *optarg;
|
||
|
extern int optind;
|
||
|
int num_addr_listen;
|
||
|
|
||
|
int *listen_sockets;
|
||
|
|
||
|
parse_cmdline(argc, argv);
|
||
|
|
||
|
num_addr_listen = start_listen_sockets(&listen_sockets, addr_listen);
|
||
|
|
||
|
main_loop(listen_sockets, num_addr_listen);
|
||
|
|
||
|
return 0;
|
||
|
}
|