From 3b104903087460158fd79c9cae27ada2d4dc103e Mon Sep 17 00:00:00 2001 From: Franklin Wei Date: Mon, 14 Jul 2014 22:31:04 -0400 Subject: Added some features to telnet server --- server.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- util.c | 14 ++++++++ util.h | 11 ++++++ 3 files changed, 135 insertions(+), 7 deletions(-) diff --git a/server.c b/server.c index 629d976..290739e 100644 --- a/server.c +++ b/server.c @@ -19,6 +19,7 @@ */ #include "joshua.h" +#include "util.h" #include #include #include @@ -29,10 +30,11 @@ #include #include #include - +#define DEFAULT_PORT 23 int server_socket; uint16_t port; int pipes[FD_SETSIZE][2]; +struct connection_data_t connection_data[FD_SETSIZE]; int make_server_socket(uint16_t port) { int sock; @@ -40,7 +42,7 @@ int make_server_socket(uint16_t port) sock=socket(AF_INET, SOCK_STREAM, 0); if(sock<0) { - printf("error creating socket.\n"); + printf("error opening socket.\n"); return -1; } name.sin_family=AF_INET; @@ -56,7 +58,7 @@ int make_server_socket(uint16_t port) } int process_data(int fd) { - char buf[1024]; + unsigned char buf[1024]; memset(buf, 0, sizeof(buf)); int ret=read(fd, buf, sizeof(buf)); char ctrl_c[]={0xff, 0xf4, 0xff, 0xfd, 0x06, 0x00}; @@ -78,7 +80,91 @@ int process_data(int fd) else { printf("Client sends: %s\n", buf); - write(pipes[fd][1], buf, strlen(buf)); + if(strlen(buf)>0) + { + if(buf[0]==0xff) + { + printf("String is command.\n"); + printf("Hex dump: "); + for(int i=0;buf[i];++i) + { + printf("%d ", buf[i]); + } + if(strlen(buf)<2) + { + printf("Bad command (length<3).\n"); + return 0; /* not a fatal error */ + } + unsigned char cmd=buf[1]; +#define WILL 251 +#define WONT 252 +#define DO 253 +#define DONT 254 +#define SB 250 +#define SE 240 +#define AYT 246 +#define NAWS 31 + unsigned char opt=(strlen(buf)==2)?0:buf[2]; + unsigned char nop[2]={0xff, 241}; + switch(cmd) + { + case AYT: + /* respond with IAC NOP */ + write(fd, nop, 2); + break; + case WILL: + case DO: + if(cmd==NAWS) + { + printf("Client offers NAWS\n"); + } + else if(cmd==1) + { + printf("Client offers echo.\n"); + } + break; + case WONT: + case DONT: + if(cmd==NAWS) + { + printf("Client denies NAWS.\n"); + } + else if(cmd==1) + { + printf("Client denies echo.\n"); + } + break; + default: + printf("Unknown command.\n"); + break; + } + if(cmd==SB) + { + if(opt==NAWS) + { + if(strlen(buf)>=9) + { + uint16_t width, height; + uint8_t width_hi, width_lo, height_hi, height_lo; + width_hi=buf[3]; + width_lo=buf[4]; + height_hi=buf[5]; + height_lo=buf[6]; + width=(width_hi<<8)|width_lo; + height=(height_hi<<8)|height_lo; + connection_data[fd].know_termsize=(width==0 || height==0)?0:1; /* if any dimension is zero, unknown */ + connection_data[fd].term_height=height; + connection_data[fd].term_width=width; + printf("Client window is %dx%d\n", width, height); + } + } + } + } + else + { + write(pipes[fd][1], buf, strlen(buf)); + } + } return 0; } } @@ -88,14 +174,29 @@ void serv_cleanup() fflush(stdout); shutdown(server_socket, SHUT_RDWR); } +void setup_new_connection(int fd) +{ + unsigned char will_naws[]={0xff, 251, 31}; + write(fd, will_naws, sizeof(will_naws)); + memset(&connection_data[fd], 0, sizeof(struct connection_data_t)); +} int main(int argc, char* argv[]) { if(argc!=2) { - printf("Usage: %s PORT\n", argv[0]); - return 2; + printf("Listening on default port: %d\n", DEFAULT_PORT); + port=DEFAULT_PORT; + } + else + { + int port2=atoi(argv[1]); + if(port2<0 || port2>65535) + { + printf("Port out of range.\n"); + return 2; + } + port=atoi(argv[1]); } - port=atoi(argv[1]); printf("Initializing server on port %u...\n", port); signal(SIGINT, &serv_cleanup); int sock=make_server_socket(port); @@ -144,6 +245,8 @@ int main(int argc, char* argv[]) pid_t pid=fork(); if(pid==0) /* child */ { + /* set up the connection */ + setup_new_connection(new); be_joshua(new); printf("Client exits\n"); shutdown(new, SHUT_RDWR); diff --git a/util.c b/util.c index 9539b46..c27981a 100644 --- a/util.c +++ b/util.c @@ -69,6 +69,7 @@ void refresh(void) } int getnstr(char* buf, int max) { + echo_on(); memset(buf, 0, max); int ret=read(pipes[out_fd][0], buf, max); if(ret!=0) @@ -81,4 +82,17 @@ int getnstr(char* buf, int max) if(ret<0) return ERR; return OK; + echo_off(); +} +void echo_off(void) +{ + unsigned char echo_off[]={0xff, 254, 1}; + write(out_fd, echo_off, 3); + fsync(out_fd); +} +void echo_on(void) +{ + unsigned char echo_on[]={0xff, 253, 1}; + write(out_fd, echo_on, 3); + fsync(out_fd); } diff --git a/util.h b/util.h index 5f7e170..6b824fd 100644 --- a/util.h +++ b/util.h @@ -19,12 +19,23 @@ */ #define SLEEP_TIME 5000 +#include +#include +struct connection_data_t { + int naws_enable:1; + int know_termsize:1; + uint16_t term_height; + uint16_t term_width; +}; +extern struct connection_data_t connection_data[FD_SETSIZE]; void allLower(char*); void print_string(const char*); void remove_punct(char*); void refresh(void); void clear(void); int getnstr(char*, int); +void echo_off(void); +void echo_on(void); #define ERR 1 #define OK 0 extern int out_fd; -- cgit v1.1