247 lines
4.9 KiB
C
247 lines
4.9 KiB
C
/*
|
|
* RFC2217 test server
|
|
*/
|
|
#include <poll.h>
|
|
#include <signal.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "lib/nvt_log.h"
|
|
#include "lib/nvt_socket.h"
|
|
#include "telnet.h"
|
|
|
|
|
|
/**INDENT-OFF**/
|
|
static const char help_text[] =
|
|
"Usage: nvtsrv OPTIONS... HOST:PORT\n"
|
|
"OPTIONS:\n"
|
|
" -d : Enable debug\n"
|
|
" -e : Echo received data\n"
|
|
" -q : Quiet\n"
|
|
;
|
|
/**INDENT-ON**/
|
|
|
|
struct {
|
|
unsigned char mline;
|
|
tn_ctx_t *tnct;
|
|
} dd;
|
|
|
|
struct pollfd pfds[3];
|
|
int nfds;
|
|
|
|
#define fd_srv pfds[1].fd
|
|
#define fd_cli pfds[2].fd
|
|
|
|
|
|
static void _usage(int rc)
|
|
{
|
|
printf(help_text);
|
|
exit(rc);
|
|
}
|
|
|
|
static void _tn_cli_close(void)
|
|
{
|
|
int i = 2;
|
|
|
|
nvt_log(LOG_INFO, "%d: fd=%d: Closed\n", i, pfds[i].fd);
|
|
close(pfds[i].fd);
|
|
pfds[i].fd = -1;
|
|
nfds = 2;
|
|
}
|
|
|
|
static void _tn_tx(void *cctx, const void *buf, int len)
|
|
{
|
|
int nw;
|
|
|
|
DBG2_BUF("Tx", buf, len);
|
|
|
|
if (fd_cli < 0)
|
|
{
|
|
nvt_log(LOG_NOTICE, "Write fd is closed - drop Tx\n");
|
|
return;
|
|
}
|
|
|
|
nw = write(fd_cli, buf, len);
|
|
if (nw != len)
|
|
{
|
|
nvt_log(LOG_ERR, "Write failed %d != %d\n", nw, len);
|
|
_tn_cli_close();
|
|
}
|
|
}
|
|
|
|
static void _tn_ss(void *cctx, int signal, int value)
|
|
{
|
|
DBG("RFC2217 signal %d: %02x", signal, value);
|
|
}
|
|
|
|
static void _nvtsrv_init(void)
|
|
{
|
|
free(dd.tnct);
|
|
|
|
memset(&dd, 0, sizeof(dd));
|
|
|
|
dd.tnct = telnet_ctx_init(NULL, _tn_tx, _tn_ss);
|
|
}
|
|
|
|
static void _nvtsrv_cmd(tn_ctx_t *tcc, const char *line, int len)
|
|
{
|
|
int val;
|
|
|
|
if (line[0] == '*' && len > 2)
|
|
{
|
|
/* Special features */
|
|
if (line[1] == 'm')
|
|
{
|
|
sscanf(line + 2, "%x", &val);
|
|
telnet_rfc2217_change_modemstate(tcc, val);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Send all input */
|
|
_tn_tx(NULL, line, len);
|
|
}
|
|
}
|
|
|
|
static void _nvtsrv_set_signal_handlers(void)
|
|
{
|
|
struct sigaction sa = {
|
|
.sa_handler = SIG_IGN,
|
|
.sa_flags = SA_RESTART,
|
|
};
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
sigaction(SIGPIPE, &sa, NULL);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int opt;
|
|
char buf[128];
|
|
int rc, nr, i, len;
|
|
int debug, quiet;
|
|
bool do_echo;
|
|
|
|
debug = quiet = 0;
|
|
do_echo = false;
|
|
|
|
while ((opt = getopt(argc, argv, "deq")) != -1)
|
|
{
|
|
switch (opt)
|
|
{
|
|
default: /* '?' */
|
|
_usage(0);
|
|
break;
|
|
case 'd':
|
|
debug += 1;
|
|
break;
|
|
case 'e': /* Echo received data */
|
|
do_echo = true;
|
|
break;
|
|
case 'q':
|
|
quiet = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
argc -= optind;
|
|
argv += optind;
|
|
if (argc <= 0)
|
|
_usage(1);
|
|
|
|
nvt_log_level(quiet, debug);
|
|
nvt_log_dest(NVT_LOG_STDOUT);
|
|
|
|
_nvtsrv_set_signal_handlers();
|
|
|
|
memset(pfds, 0, sizeof(pfds));
|
|
|
|
pfds[0].fd = STDIN_FILENO;
|
|
pfds[0].events = POLLIN;
|
|
|
|
pfds[1].fd = socket_create_server(argv[0]);
|
|
pfds[1].events = POLLIN;
|
|
|
|
pfds[2].fd = -1;
|
|
pfds[2].events = POLLIN;
|
|
|
|
nfds = 2;
|
|
|
|
for (;;)
|
|
{
|
|
for (i = 0; i < 3; i++)
|
|
pfds[i].revents = 0;
|
|
|
|
rc = poll(pfds, nfds, -1);
|
|
if (rc < 0)
|
|
{
|
|
nvt_log(LOG_ERR, "poll failed: %m\n");
|
|
break;
|
|
}
|
|
|
|
i = 0;
|
|
if (pfds[i].revents)
|
|
{
|
|
nr = read(pfds[i].fd, buf, sizeof(buf) - 1);
|
|
if (nr <= 0)
|
|
break;
|
|
buf[nr] = 0;
|
|
DBG2_BUF("Con Rx", buf, nr);
|
|
_nvtsrv_cmd(dd.tnct, buf, nr);
|
|
}
|
|
|
|
i = 2;
|
|
if (pfds[i].revents)
|
|
{
|
|
nr = 0;
|
|
if (pfds[i].revents & POLLIN)
|
|
{
|
|
nr = read(pfds[i].fd, buf, sizeof(buf));
|
|
if (nr <= 0)
|
|
{
|
|
_tn_cli_close();
|
|
continue;
|
|
}
|
|
}
|
|
if (pfds[i].revents & (POLLERR | POLLHUP))
|
|
{
|
|
_tn_cli_close();
|
|
}
|
|
|
|
if (nr > 0)
|
|
{
|
|
buf[nr] = 0;
|
|
DBG2_BUF("Rx", buf, nr);
|
|
len = nr;
|
|
rc = telnet_rx(dd.tnct, buf, &len);
|
|
if (do_echo)
|
|
{
|
|
/* Echo received */
|
|
_tn_tx(NULL, buf, len);
|
|
}
|
|
}
|
|
}
|
|
|
|
i = 1;
|
|
if (pfds[i].revents)
|
|
{
|
|
if (pfds[2].fd >= 0)
|
|
{
|
|
nvt_log(LOG_NOTICE, "Client already connected on fd=%d\n",
|
|
pfds[2].fd);
|
|
break;
|
|
}
|
|
pfds[2].fd = socket_create_server_client(pfds[i].fd);
|
|
nvt_log(LOG_INFO, "%d: fd=%d: Connected\n", 2, pfds[2].fd);
|
|
pfds[2].events = POLLIN;
|
|
nfds = 3;
|
|
_nvtsrv_init();
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|