diff --git a/include/netutils/telnetc.h b/include/netutils/telnetc.h index d3f87a95b..394d3a629 100644 --- a/include/netutils/telnetc.h +++ b/include/netutils/telnetc.h @@ -1,5 +1,5 @@ /**************************************************************************** - * apps/netutils/telnetc/telnetc.c + * apps/include/netutils/telnetc.h * * Leveraged from libtelnet, https://github.com/seanmiddleditch/libtelnet. * Modified and re-released under the BSD license: @@ -208,7 +208,7 @@ extern "C" /* Error codes */ -enum telnet_error_u +enum telnet_error_e { TELNET_EOK = 0, /* No error */ TELNET_EBADVAL, /* Invalid parameter, or API misuse */ @@ -284,7 +284,7 @@ union telnet_event_u const char *func; /* Function the error occured in */ const char *msg; /* Error message string */ int line; /* Line of file error occured on */ - enum telnet_error_u errcode; /* Error code */ + enum telnet_error_e errcode; /* Error code */ } error; /* Command event: for IAC */ diff --git a/netutils/telnetc/telnetc.c b/netutils/telnetc/telnetc.c index d27e93ced..a95c659ed 100644 --- a/netutils/telnetc/telnetc.c +++ b/netutils/telnetc/telnetc.c @@ -197,8 +197,8 @@ static const size_t _buffer_sizes_count = sizeof(_buffer_sizes) / /* Error generation function */ -static enum telnet_error_u _error(struct telnet_s *telnet, unsigned line, - const char *func, enum telnet_error_u err, +static enum telnet_error_e _error(struct telnet_s *telnet, unsigned line, + const char *func, enum telnet_error_e err, int fatal, const char *fmt, ...) { union telnet_event_u ev; @@ -230,7 +230,7 @@ static enum telnet_error_u _error(struct telnet_s *telnet, unsigned line, */ #if defined(HAVE_ZLIB) -enum telnet_error_u _init_zlib(struct telnet_s *telnet, int deflate, +enum telnet_error_e _init_zlib(struct telnet_s *telnet, int deflate, int err_fatal) { z_stream *z; @@ -361,7 +361,7 @@ static inline int _check_telopt(struct telnet_s *telnet, return 0; } - /* Loop unti found or end marker (us and him both 0) */ + /* Loop until found or end marker (us and him both 0) */ for (i = 0; telnet->telopts[i].telopt != -1; ++i) { @@ -441,7 +441,7 @@ static inline void _set_rfc1143(struct telnet_s *telnet, unsigned char telopt, qtmp = (struct telnet_rfc1143_s *) realloc(telnet->q, - sizeof(struct telnet_rfc1143_s) * (telnet->q_size + 4)); + sizeof(struct telnet_rfc1143_s) * (telnet->q_size + 4)); if (qtmp == 0) { _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0, @@ -713,7 +713,7 @@ static int _environ_telnet(struct telnet_s *telnet, unsigned char type, ev.type = TELNET_EV_ENVIRON; telnet->eh(telnet, &ev, telnet->ud); - return 1; + return 0; } /* Every second byte must be VAR or USERVAR, if present */ @@ -854,7 +854,7 @@ static int _environ_telnet(struct telnet_s *telnet, unsigned char type, /* Clean up */ free(values); - return 1; + return 0; } /* Process an MSSP subnegotiation buffer */ @@ -1104,21 +1104,17 @@ static int _subnegotiate(struct telnet_s *telnet) */ case TELNET_TELOPT_COMPRESS2: - if (telnet->sb_telopt == TELNET_TELOPT_COMPRESS2) + if (_init_zlib(telnet, 0, 1) != TELNET_EOK) { - if (_init_zlib(telnet, 0, 1) != TELNET_EOK) - { - return 0; - } - - /* Notify app that compression was enabled */ - - ev.type = TELNET_EV_COMPRESS; - ev.compress.state = 1; - telnet->eh(telnet, &ev, telnet->ud); - return 1; + return 0; } - return 0; + + /* Notify app that compression was enabled */ + + ev.type = TELNET_EV_COMPRESS; + ev.compress.state = 1; + telnet->eh(telnet, &ev, telnet->ud); + return 1; #endif /* HAVE_ZLIB */ /* Specially handled subnegotiation telopt types */ @@ -1248,7 +1244,7 @@ void telnet_free(struct telnet_s *telnet) /* Push a byte into the telnet buffer */ -static enum telnet_error_u _buffer_byte(struct telnet_s *telnet, +static enum telnet_error_e _buffer_byte(struct telnet_s *telnet, unsigned char byte) { char *new_buffer; @@ -2283,6 +2279,11 @@ void telnet_ttype_is(struct telnet_s *telnet, const char *ttype) TELNET_IAC, TELNET_SB, TELNET_TELOPT_TTYPE, TELNET_TTYPE_IS }; + if (!ttype) + { + ttype = "NVT"; + } + _sendu(telnet, IS, sizeof(IS)); _send(telnet, ttype, strlen(ttype)); telnet_finish_sb(telnet); diff --git a/system/telnet/Make.defs b/system/telnet/Make.defs index 12fe718d1..0e0954ab7 100644 --- a/system/telnet/Make.defs +++ b/system/telnet/Make.defs @@ -1,5 +1,5 @@ ############################################################################ -# apps/system/usbmsc/Make.defs +# apps/system/telnet/Make.defs # Adds selected applications to apps/ build # # Copyright (C) 2016 Gregory Nutt. All rights reserved. diff --git a/system/telnet/telnet_chatd.c b/system/telnet/telnet_chatd.c index 6d51ead39..17c4a7d1a 100644 --- a/system/telnet/telnet_chatd.c +++ b/system/telnet/telnet_chatd.c @@ -107,6 +107,23 @@ static struct user_s g_users[MAX_USERS]; * Private Functions ****************************************************************************/ +static void cleanup_exit(void) +{ + int i; + + for (i = 0; i != MAX_USERS; ++i) + { + if (g_users[i].sock != -1) + { + close(g_users[i].sock); + free(g_users[i].name); + telnet_free(g_users[i].telnet); + } + } + + exit(1); +} + static void linebuffer_push(char *buffer, size_t size, int *linepos, char ch, void (*cb) (const char *line, int overflow, void *ud), void *ud) @@ -180,7 +197,7 @@ static void _send(int sock, const char *buffer, unsigned int size) if (errno != EINTR && errno != ECONNRESET) { fprintf(stderr, "send() failed: %d\n", errno); - exit(1); + cleanup_exit(); } else { @@ -190,7 +207,7 @@ static void _send(int sock, const char *buffer, unsigned int size) else if (ret == 0) { fprintf(stderr, "send() unexpectedly returned 0\n"); - exit(1); + cleanup_exit(); } /* Update pointer and size to see if we've got more to send */ @@ -246,6 +263,7 @@ static void _online(const char *line, int overflow, void *ud) _message(user->name, "** HAS QUIT **"); free(user->name); user->name = 0; + telnet_free(user->telnet); return; } @@ -258,7 +276,7 @@ static void _input(struct user_s *user, const char *buffer, unsigned int size) { unsigned int i; - for (i = 0; i != size; ++i) + for (i = 0; user->sock != -1 && i != size; ++i) { linebuffer_push(user->linebuf, sizeof(user->linebuf), &user->linepos, (char)buffer[i], _online, user); @@ -420,12 +438,12 @@ int main(int argc, FAR char *argv[]) if (ret == -1 && errno != EINTR) { fprintf(stderr, "poll() failed: %d\n", errno); - return 1; + cleanup_exit(); } /* New connection */ - if (pfd[MAX_USERS].revents & POLLIN) + if (pfd[MAX_USERS].revents & (POLLIN | POLLERR | POLLHUP)) { /* Accept the sock */ @@ -434,7 +452,7 @@ int main(int argc, FAR char *argv[]) &addrlen)) == -1) { fprintf(stderr, "accept() failed: %d\n", errno); - return 1; + cleanup_exit(); } printf("Connection received.\n"); @@ -478,7 +496,7 @@ int main(int argc, FAR char *argv[]) continue; } - if (pfd[i].revents & POLLIN) + if (pfd[i].revents & (POLLIN | POLLERR | POLLHUP)) { if ((ret = recv(g_users[i].sock, buffer, sizeof(buffer), 0)) > 0) { @@ -488,6 +506,7 @@ int main(int argc, FAR char *argv[]) { printf("Connection closed.\n"); close(g_users[i].sock); + g_users[i].sock = -1; if (g_users[i].name != 0) { _message(g_users[i].name, "** HAS DISCONNECTED **"); @@ -496,13 +515,11 @@ int main(int argc, FAR char *argv[]) } telnet_free(g_users[i].telnet); - g_users[i].sock = -1; - break; } else if (errno != EINTR) { fprintf(stderr, "recv(client) failed: %d\n", errno); - exit(1); + cleanup_exit(); } } } diff --git a/system/telnet/telnet_client.c b/system/telnet/telnet_client.c index 6f1d3549d..04c17a7b4 100644 --- a/system/telnet/telnet_client.c +++ b/system/telnet/telnet_client.c @@ -156,14 +156,17 @@ static void telnet_ev_send(int sock, const char *buffer, size_t size) while (size > 0) { - if ((ret = send(sock, buffer, size, 0)) == -1) + if ((ret = send(sock, buffer, size, 0)) <= 0) { - fprintf(stderr, "send() failed: %d\n", errno); - exit(1); - } - else if (ret == 0) - { - fprintf(stderr, "send() unexpectedly returned 0\n"); + if (ret < 0) + { + fprintf(stderr, "send() failed: %d\n", errno); + } + else + { + fprintf(stderr, "send() unexpectedly returned 0\n"); + } + telnet_free(g_telnet); exit(1); } @@ -245,6 +248,7 @@ static void _event_handler(struct telnet_s *telnet, case TELNET_EV_ERROR: fprintf(stderr, "ERROR: %s\n", ev->error.msg); + telnet_free(g_telnet); exit(1); default: @@ -264,7 +268,7 @@ static void show_usage(const char *progname, int exitcode) fprintf(stderr, "\t\tIPv6 form: xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx\n"); fprintf(stderr, "\t is the (optional) listening port of the Telnet server.\n"); fprintf(stderr, "\t\tDefault: %u\n", DEFAULT_PORT); - exit(exitcode) ; + exit(exitcode); } /**************************************************************************** @@ -337,7 +341,7 @@ int main(int argc, FAR char *argv[]) server.ipv6.sin6_port = htons(portno); ret = inet_pton(AF_INET6, argv[1], server.ipv6.sin6_addr.s6_addr); - if (ret < 0) + if (ret <= 0) #endif #ifdef CONFIG_NET_IPv4 { @@ -351,7 +355,7 @@ int main(int argc, FAR char *argv[]) ret = inet_pton(AF_INET, argv[1], &server.ipv4.sin_addr); } - if (ret < 0) + if (ret <= 0) #endif { fprintf(stderr, "ERROR: is invalid\n"); @@ -407,40 +411,40 @@ int main(int argc, FAR char *argv[]) { /* Read from stdin */ - if (pfd[0].revents & POLLIN) + if (pfd[0].revents & (POLLIN | POLLERR | POLLHUP)) { ret = std_readline(buffer, sizeof(buffer)); if (ret > 0) { send_local_input(buffer, ret); } - else if (ret == 0) - { - break; - } else { - fprintf(stderr, "recv(server) failed: %d\n", errno); - exit(1); + if (ret < 0) + { + fprintf(stderr, "recv(server) failed: %d\n", errno); + ret = 1; + } + break; } } /* Read from client */ - if (pfd[1].revents & POLLIN) + if (pfd[1].revents & (POLLIN | POLLERR | POLLHUP)) { if ((ret = recv(sock, buffer, sizeof(buffer), 0)) > 0) { telnet_recv(g_telnet, buffer, ret); } - else if (ret == 0) - { - break; - } else { - fprintf(stderr, "recv(client) failed: %d\n", errno); - exit(1); + if (ret < 0) + { + fprintf(stderr, "recv(client) failed: %d\n", errno); + ret = 1; + } + break; } } } @@ -449,5 +453,5 @@ int main(int argc, FAR char *argv[]) telnet_free(g_telnet); close(sock); - return 0; + return ret; }