Extract telnet functions into a separate header
This commit is contained in:
parent
f1372827c1
commit
c59b2138f4
4 changed files with 110 additions and 108 deletions
|
@ -193,7 +193,9 @@ int main(int argc, char *argv[]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* put client in "character" mode */
|
/* put client in "character" mode */
|
||||||
telnet_set_character_mode(&client);
|
char msg[TELNET_MSG_SIZE_CHARMODE];
|
||||||
|
telnet_message_set_character_mode(msg);
|
||||||
|
client_write(&client, msg, TELNET_MSG_SIZE_CHARMODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* setup parameters for select() */
|
/* setup parameters for select() */
|
||||||
|
|
29
moxerver.h
29
moxerver.h
|
@ -12,6 +12,8 @@
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <telnet.h>
|
||||||
|
|
||||||
#define DATABUF_LEN 128
|
#define DATABUF_LEN 128
|
||||||
#define DEV_PATH 128
|
#define DEV_PATH 128
|
||||||
#define TIMESTAMP_FORMAT "%Y-%m-%dT%H:%M:%S" /* ISO 8601 */
|
#define TIMESTAMP_FORMAT "%Y-%m-%dT%H:%M:%S" /* ISO 8601 */
|
||||||
|
@ -159,34 +161,7 @@ int client_wait_line(client_t *client);
|
||||||
int client_ask_username(client_t *client);
|
int client_ask_username(client_t *client);
|
||||||
|
|
||||||
|
|
||||||
/* Functions handling details related to telnet protocol. */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells client to go into "character" mode.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* - 0 on success
|
|
||||||
* - negative value if error occurred
|
|
||||||
*/
|
|
||||||
int telnet_set_character_mode(client_t *client);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles special characters in data buffer after receiving them from client.
|
|
||||||
* Used to filter out handshake commands of telnet protocol.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* 0 always
|
|
||||||
*/
|
|
||||||
int telnet_handle_client_read(char *databuf, int *datalen);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles special characters in data buffer before sending to client.
|
|
||||||
* Used for echoing characters correctly to telnet client.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* 0 always
|
|
||||||
*/
|
|
||||||
int telnet_handle_client_write(char *databuf, int *datalen);
|
|
||||||
|
|
||||||
|
|
||||||
/* Functions handling communication with tty device. */
|
/* Functions handling communication with tty device. */
|
||||||
|
|
156
telnet.c
156
telnet.c
|
@ -1,8 +1,5 @@
|
||||||
/*
|
#include <telnet.h>
|
||||||
* Handling details related to telnet protocol.
|
#include <moxerver.h>
|
||||||
*/
|
|
||||||
|
|
||||||
#include "moxerver.h"
|
|
||||||
|
|
||||||
/* structure for holding telnet option name and value */
|
/* structure for holding telnet option name and value */
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -12,7 +9,8 @@ typedef struct
|
||||||
} telnet_option_t;
|
} telnet_option_t;
|
||||||
|
|
||||||
/* supported telnet option values */
|
/* supported telnet option values */
|
||||||
telnet_option_t telnet_options[] = {
|
telnet_option_t telnet_options[] =
|
||||||
|
{
|
||||||
{"WILL", 251},
|
{"WILL", 251},
|
||||||
{"WONT", 252},
|
{"WONT", 252},
|
||||||
{"DO", 253},
|
{"DO", 253},
|
||||||
|
@ -25,118 +23,118 @@ telnet_option_t telnet_options[] = {
|
||||||
/* this list must end with {NULL, 0} */
|
/* this list must end with {NULL, 0} */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Returns telnet option name based on the value. */
|
/* Returns the name of a telnet option based on the value. */
|
||||||
static const char* telnet_option_name(int value) {
|
static const char* telnet_option_name(int value)
|
||||||
int i = 0;
|
{
|
||||||
while (telnet_options[i].name) {
|
int i;
|
||||||
if (telnet_options[i].value == value) return telnet_options[i].name;
|
for (i = 0; telnet_options[i].name != NULL; i++)
|
||||||
i++;
|
{
|
||||||
|
if (telnet_options[i].value == value)
|
||||||
|
{
|
||||||
|
return telnet_options[i].name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/* default value */
|
||||||
return '\0';
|
return '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns telnet option value based on the name. */
|
/* Returns the value of a telnet option based on the name. */
|
||||||
static char telnet_option_value(const char* name) {
|
static char telnet_option_value(const char* name)
|
||||||
int i = 0;
|
{
|
||||||
while (telnet_options[i].name) {
|
int i;
|
||||||
if (!strcmp(telnet_options[i].name, name)) return telnet_options[i].value;
|
for (i = 0; telnet_options[i].name != NULL; i++)
|
||||||
i++;
|
{
|
||||||
|
if (strcmp(telnet_options[i].name, name) == 0)
|
||||||
|
{
|
||||||
|
return telnet_options[i].value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/* default value */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sends telnet option command. Returns 0 on success, -1 on failure. */
|
/* Handles a received telnet option command. */
|
||||||
static int telnet_send_command(client_t *client, const char* option, const char* command) {
|
static void telnet_handle_command(char *databuf, int datalen)
|
||||||
|
{
|
||||||
char data[3];
|
/* just print received commands:
|
||||||
|
* we set the client, we don't adapt to client commands */
|
||||||
/* pack command */
|
if (databuf[0] == telnet_option_value("IAC"))
|
||||||
data[0] = telnet_option_value("IAC");
|
{
|
||||||
data[1] = telnet_option_value(option);
|
|
||||||
data[2] = telnet_option_value(command);
|
|
||||||
|
|
||||||
/* send command */
|
|
||||||
if (client_write(client, data, 3) <= 0) {
|
|
||||||
fprintf(stderr, "[%s:%d] failed sending %s %s\n", __func__, __LINE__, option, command);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "[%s] sent %s %s\n", __func__, option, command);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handles received telnet option command. Always returns 0.*/
|
|
||||||
static int telnet_handle_command(char *databuf, int datalen) {
|
|
||||||
|
|
||||||
/* currently just print received commands because we set the client, we don't adapt to client commands */
|
|
||||||
if (databuf[0] == telnet_option_value("IAC")) {
|
|
||||||
fprintf(stderr, "[%s] received %s %s\n", __func__,
|
fprintf(stderr, "[%s] received %s %s\n", __func__,
|
||||||
telnet_option_name(databuf[1]), telnet_option_name(databuf[2]));
|
telnet_option_name(databuf[1]),
|
||||||
|
telnet_option_name(databuf[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tells client to go into "character" mode. */
|
void telnet_message_set_character_mode(char *databuf)
|
||||||
int telnet_set_character_mode(client_t *client) {
|
{
|
||||||
|
/* send a predefined set of commands proven to work */
|
||||||
|
|
||||||
int err = 0;
|
databuf[0] = telnet_option_value("IAC");
|
||||||
|
databuf[1] = telnet_option_value("WILL");
|
||||||
|
databuf[2] = telnet_option_value("ECHO");
|
||||||
|
|
||||||
/* send predefined commands and add up their return vaules */
|
databuf[3] = telnet_option_value("IAC");
|
||||||
err += telnet_send_command(client, "WILL", "ECHO");
|
databuf[4] = telnet_option_value("WILL");
|
||||||
err += telnet_send_command(client, "WILL", "SGA");
|
databuf[5] = telnet_option_value("SGA");
|
||||||
err += telnet_send_command(client, "WONT", "LINEMODE"); /* this depends on telnet client */
|
|
||||||
|
/* this one really depends on telnet client */
|
||||||
|
databuf[6] = telnet_option_value("IAC");
|
||||||
|
databuf[7] = telnet_option_value("WONT");
|
||||||
|
databuf[8] = telnet_option_value("LINEMODE");
|
||||||
|
|
||||||
//TODO Do we verify client response? What do we do if the response is not how we expected?
|
//TODO Do we verify client response? What do we do if the response is not how we expected?
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles special characters in data buffer after receiving them from client.
|
void telnet_handle_client_read(char *databuf, int *datalen)
|
||||||
* Used to filter out handshake commands of telnet protocol. */
|
{
|
||||||
int telnet_handle_client_read(char *databuf, int *datalen) {
|
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
char newdata[DATABUF_LEN];
|
char newdata[DATABUF_LEN];
|
||||||
int newlen = 0;
|
int newlen = 0;
|
||||||
|
|
||||||
/* process data using a new buffer */
|
/* process data using a new buffer */
|
||||||
for (i = 0; i < *datalen; i++) {
|
for (i = 0; i < *datalen; i++)
|
||||||
|
{
|
||||||
/* handle and discard telnet commands */
|
/* handle and discard telnet commands */
|
||||||
if (databuf[i] == telnet_option_value("IAC")) {
|
if (databuf[i] == telnet_option_value("IAC"))
|
||||||
|
{
|
||||||
telnet_handle_command((databuf+i), 3);
|
telnet_handle_command((databuf+i), 3);
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
/* let other data pass through */
|
/* let other data pass through */
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
newdata[newlen++] = databuf[i];
|
newdata[newlen++] = databuf[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* overwrite data with new buffer */
|
/* overwrite the data with the new buffer */
|
||||||
for (i = 0; i < newlen; i++) databuf[i] = newdata[i];
|
for (i = 0; i < newlen; i++)
|
||||||
|
{
|
||||||
|
databuf[i] = newdata[i];
|
||||||
|
}
|
||||||
|
/* update data length */
|
||||||
*datalen = newlen;
|
*datalen = newlen;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles special characters in data buffer before sending to client.
|
void telnet_handle_client_write(char *databuf, int *datalen)
|
||||||
* Used for echoing characters correctly to telnet client. */
|
{
|
||||||
int telnet_handle_client_write(char *databuf, int *datalen) {
|
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
char newdata[DATABUF_LEN];
|
char newdata[DATABUF_LEN]; // TODO: maybe use realloc, this is risky
|
||||||
int newlen = 0;
|
int newlen = 0;
|
||||||
|
|
||||||
/* process data using a new buffer */
|
/* process data using a new buffer */
|
||||||
for (i = 0; i < *datalen; i++) {
|
for (i = 0; i < *datalen; i++)
|
||||||
|
{
|
||||||
/* pressed ENTER */
|
/* pressed ENTER */
|
||||||
if (databuf[i] == 13) {
|
if (databuf[i] == 13)
|
||||||
|
{
|
||||||
fprintf(stderr, "[%s] handling ENTER\n", __func__);
|
fprintf(stderr, "[%s] handling ENTER\n", __func__);
|
||||||
newdata[newlen++] = '\r';
|
newdata[newlen++] = '\r';
|
||||||
newdata[newlen++] = '\n';
|
newdata[newlen++] = '\n';
|
||||||
}
|
}
|
||||||
/* pressed BACKSPACE */
|
/* pressed BACKSPACE */
|
||||||
if (databuf[i] == 127) {
|
if (databuf[i] == 127)
|
||||||
|
{
|
||||||
fprintf(stderr, "[%s] handling BACKSPACE\n", __func__);
|
fprintf(stderr, "[%s] handling BACKSPACE\n", __func__);
|
||||||
newdata[newlen++] = 8;
|
newdata[newlen++] = 8;
|
||||||
newdata[newlen++] = ' ';
|
newdata[newlen++] = ' ';
|
||||||
|
@ -146,9 +144,11 @@ int telnet_handle_client_write(char *databuf, int *datalen) {
|
||||||
newdata[newlen++] = databuf[i];
|
newdata[newlen++] = databuf[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* overwrite data with new buffer */
|
/* overwrite the data with the new buffer */
|
||||||
for (i = 0; i < newlen; i++) databuf[i] = newdata[i];
|
for (i = 0; i < newlen; i++)
|
||||||
|
{
|
||||||
|
databuf[i] = newdata[i];
|
||||||
|
}
|
||||||
|
/* update data length */
|
||||||
*datalen = newlen;
|
*datalen = newlen;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
25
telnet.h
Normal file
25
telnet.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/* Handles details related to telnet protocol. */
|
||||||
|
|
||||||
|
#define TELNET_MSG_SIZE_CHARMODE 9
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a telnet protocol message that tells client to go into "character"
|
||||||
|
* mode. The passed data buffer must be big enough to hold the message payload
|
||||||
|
* with the size defined by TELNET_MSG_SIZE_CHARMODE.
|
||||||
|
* Operates directly on the passed data buffer.
|
||||||
|
*/
|
||||||
|
void telnet_message_set_character_mode(char *databuf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles special characters in the data buffer after receiving them from the
|
||||||
|
* client. Used to filter out the handshake commands of telnet protocol.
|
||||||
|
* Operates directly on the passed data buffer and modifies the payload length.
|
||||||
|
*/
|
||||||
|
void telnet_handle_client_read(char *databuf, int *datalen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles special characters in the data buffer before sending them to the
|
||||||
|
* client. Used to correctly echo the characters to the telnet client.
|
||||||
|
* Operates directly on the passed data buffer and modifies the payload length.
|
||||||
|
*/
|
||||||
|
void telnet_handle_client_write(char *databuf, int *datalen);
|
Loading…
Add table
Add a link
Reference in a new issue